lists.mariadb.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

commits

Thread Start a new thread
Threads by month
  • ----- 2025 -----
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
commits@lists.mariadb.org

November 2024

  • 1 participants
  • 8 discussions
[PATCH] MDEV-31794: Preserved unsupported table flags break replication
by Kristian Nielsen 30 Nov '24

30 Nov '24
The slave replication should accept not supported table options (eg. "transactional" for MyISAM), as such options can end up being set from the master in binlogged CREATE TABLE. This was already handled in report_unknown_option(), which skips the error in slave threads. But in mysql_prepare_create_table_finalize() there was still a warning given, and this warning gets converted into an error when STRICT_(ALL|TRANS)_TABLES. So skip this warning for replication also. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- .../suite/rpl/r/rpl_row_create_table.result | 13 +++++++++++++ .../suite/rpl/t/rpl_row_create_table.test | 19 +++++++++++++++++++ sql/sql_table.cc | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_create_table.result b/mysql-test/suite/rpl/r/rpl_row_create_table.result index 197b4be2c9f..8bb229e215d 100644 --- a/mysql-test/suite/rpl/r/rpl_row_create_table.result +++ b/mysql-test/suite/rpl/r/rpl_row_create_table.result @@ -495,5 +495,18 @@ DROP VIEW IF EXISTS bug48506_t1, bug48506_t2, bug48506_t3; DROP TEMPORARY TABLES t7; DROP TABLES t4, t5; DROP TABLES IF EXISTS bug48506_t4; +*** MDEV-31794: Preserved unsupported table flags break replication +CREATE TEMPORARY TABLE t1 (a INT) ENGINE=Aria TRANSACTIONAL=1; +ALTER TABLE t1 ENGINE=MyISAM; +CREATE TABLE t2 LIKE t1; +connection slave; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci /* TRANSACTIONAL=1 */ +connection master; +DROP TEMPORARY TABLE t1; +DROP TABLE t2; include/rpl_end.inc end of the tests diff --git a/mysql-test/suite/rpl/t/rpl_row_create_table.test b/mysql-test/suite/rpl/t/rpl_row_create_table.test index b62955e2cd4..47ad0670a58 100644 --- a/mysql-test/suite/rpl/t/rpl_row_create_table.test +++ b/mysql-test/suite/rpl/t/rpl_row_create_table.test @@ -280,6 +280,25 @@ DROP TEMPORARY TABLES t7; DROP TABLES t4, t5; DROP TABLES IF EXISTS bug48506_t4; + +--echo *** MDEV-31794: Preserved unsupported table flags break replication +CREATE TEMPORARY TABLE t1 (a INT) ENGINE=Aria TRANSACTIONAL=1; +# After ALTER to MyISAM, TRANSACTIONAL=1 is a left-over option normally +# invalid for MyISAM. +ALTER TABLE t1 ENGINE=MyISAM; +# Since row-based binlogging is used, the temporary table t1 is not binlogged, +# so this CREATE TABLE LIKE is replicated as a plain CREATE TABLE which +# specifies invalid TRANSACTIONAL=1 for a MyISAM table. +# Test that the slave will still allow the create table. +CREATE TABLE t2 LIKE t1; +--sync_slave_with_master +SHOW CREATE TABLE t2; + +--connection master +DROP TEMPORARY TABLE t1; +DROP TABLE t2; + + --source include/rpl_end.inc --echo end of the tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 25ff452c109..51a1d013d19 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3876,7 +3876,7 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, /* Give warnings for not supported table options */ if (create_info->used_fields & HA_CREATE_USED_TRANSACTIONAL && - !file->has_transactional_option()) + !file->has_transactional_option() && !thd->rgi_slave) push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_OPTION, ER_THD(thd, ER_UNKNOWN_OPTION), "transactional"); -- 2.39.5
1 0
0 0
[PATCH] MDEV-33239: mysqlbinlog always stops at timestamp 0xffffffff
by Kristian Nielsen 30 Nov '24

30 Nov '24
Do not use the magic value 0xffffffff as meaning "no --stop-datetime option specified", as this is a valid timestamp value. Use an explicit boolean flag instead. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- client/mysqlbinlog.cc | 10 ++++++---- mysql-test/main/mysqlbinlog.result | 19 +++++++++++++++++++ mysql-test/main/mysqlbinlog.test | 22 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 812cde74759..5af5ca95c75 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -159,7 +159,8 @@ static Domain_gtid_event_filter *domain_id_gtid_filter= NULL; static Server_gtid_event_filter *server_id_gtid_filter= NULL; static char *start_datetime_str, *stop_datetime_str; -static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX; +static my_time_t start_datetime= 0, stop_datetime= 0; +static bool stop_datetime_given= false; static ulonglong rec_count= 0; static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; @@ -1027,7 +1028,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, if (ev_type != ROTATE_EVENT && is_server_id_excluded(ev->server_id)) goto end; } - if ((ev->when >= stop_datetime) + if ((stop_datetime_given && ev->when >= stop_datetime) || (pos >= stop_position_mot)) { /* end the program */ @@ -2120,6 +2121,7 @@ get_one_option(const struct my_option *opt, const char *argument, break; case OPT_STOP_DATETIME: stop_datetime= convert_str_to_timestamp(stop_datetime_str); + stop_datetime_given= true; break; case OPT_BASE64_OUTPUT_MODE: int val; @@ -3193,7 +3195,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, Emit a warning in the event that we finished processing input before reaching the boundary indicated by --stop-datetime. */ - if (stop_datetime != MY_TIME_T_MAX && + if (stop_datetime_given && stop_datetime > last_ev_when) { retval = OK_STOP; @@ -3300,7 +3302,7 @@ int main(int argc, char** argv) if (stop_position != (ulonglong)(~(my_off_t)0)) warning("The --stop-position option is ignored in raw mode"); - if (stop_datetime != MY_TIME_T_MAX) + if (stop_datetime_given) warning("The --stop-datetime option is ignored in raw mode"); result_file= 0; if (result_file_name) diff --git a/mysql-test/main/mysqlbinlog.result b/mysql-test/main/mysqlbinlog.result index c7b354105c2..8181a76244c 100644 --- a/mysql-test/main/mysqlbinlog.result +++ b/mysql-test/main/mysqlbinlog.result @@ -1300,4 +1300,23 @@ ERROR: Bad syntax in rewrite-db. Expected syntax is FROM->TO. ERROR: Bad syntax in rewrite-db. Expected syntax is FROM->TO. ERROR: Bad syntax in rewrite-db. Expected syntax is FROM->TO. ERROR: Bad syntax in rewrite-db. Expected syntax is FROM->TO. +# +# MDEV-33239: mysqlbinlog always stops at timestamp 0xffffffff +# +RESET MASTER; +CREATE TABLE t (a INT); +INSERT INTO t VALUES (1); +SET @@timestamp= 0 + 0xffffffff; +INSERT INTO t VALUES (2); +SELECT * FROM t ORDER BY a; +a +1 +2 +FLUSH BINARY LOGS; +DROP TABLE t; +SELECT * FROM t ORDER BY a; +a +1 +2 +DROP TABLE t; ALTER DATABASE test CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci; diff --git a/mysql-test/main/mysqlbinlog.test b/mysql-test/main/mysqlbinlog.test index 3beea178b78..4922a9b0422 100644 --- a/mysql-test/main/mysqlbinlog.test +++ b/mysql-test/main/mysqlbinlog.test @@ -641,4 +641,26 @@ FLUSH LOGS; --exec $MYSQL_BINLOG --rewrite-db=" test -> foo " --short-form $MYSQLD_DATADIR/master-bin.000001 > /dev/null 2> $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn +--echo # +--echo # MDEV-33239: mysqlbinlog always stops at timestamp 0xffffffff +--echo # + +RESET MASTER; + +CREATE TABLE t (a INT); +INSERT INTO t VALUES (1); +SET @@timestamp= 0 + 0xffffffff; +INSERT INTO t VALUES (2); +SELECT * FROM t ORDER BY a; + +FLUSH BINARY LOGS; +DROP TABLE t; + +# The bug was that mysqlbinlog would stop before the event with timestamp +# 0xffffffff, so the second insert would be missing from the table. +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 | $MYSQL test +SELECT * FROM t ORDER BY a; +DROP TABLE t; + + --source include/test_db_charset_restore.inc -- 2.39.5
1 0
0 0
[PATCH] MDEV-13831: Assertion on event group missing XID/COMMIT event
by Kristian Nielsen 29 Nov '24

29 Nov '24
The assertion occurred in the SQL thread if an event group was incompletely written, missing the end XID or COMMIT event, and immediately followed by a new event group. This could also lead to the incomplete event group being committed, and with the wrong GTID. Fix by rolling back any active transaction from a prior event group when applying the following GTID event. Getting an incomplete event like this is somewhat rare to happen. If the server crashes in the middle of writing an event group, the server restart will write a new format description event, which makes the slave roll back the partial event group. But presumably it could happen if the master experiences temporary write errors in the binlog, like intermittent disk full for example. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- mysql-test/suite/rpl/r/rpl_mdev13831.result | 29 +++++++++++++++ mysql-test/suite/rpl/t/rpl_mdev13831.test | 41 +++++++++++++++++++++ sql/log_event_server.cc | 15 +++++++- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/rpl/r/rpl_mdev13831.result create mode 100644 mysql-test/suite/rpl/t/rpl_mdev13831.test diff --git a/mysql-test/suite/rpl/r/rpl_mdev13831.result b/mysql-test/suite/rpl/r/rpl_mdev13831.result new file mode 100644 index 00000000000..0f0f25e6def --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_mdev13831.result @@ -0,0 +1,29 @@ +include/master-slave.inc +[connection master] +*** MDEV-13831: Assertion on event group missing XID/COMMIT event +connection slave; +include/stop_slave.inc +CHANGE MASTER TO Master_use_gtid= No; +include/start_slave.inc +connection master; +SET @old_legacy= @@GLOBAL.binlog_legacy_event_pos; +SET GLOBAL binlog_legacy_event_pos= 1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +connection master1; +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug = '+d,fail_binlog_write_1'; +UPDATE t1 SET a = 2; +ERROR HY000: Error writing file 'master-bin' (errno: 28 "No space left on device") +SET debug_dbug= @old_dbug; +DROP TEMPORARY TABLE t1; +ERROR 42S02: Unknown table 'test.t1' +connection master; +CREATE TEMPORARY TABLE t1 (i INT) ENGINE=InnoDB; +connection slave; +connection master; +SET GLOBAL binlog_legacy_event_pos= @old_legacy; +CALL mtr.add_suppression("Error writing file.*No space left on device"); +DROP TEMPORARY TABLE t1; +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev13831.test b/mysql-test/suite/rpl/t/rpl_mdev13831.test new file mode 100644 index 00000000000..5b86e21cda0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mdev13831.test @@ -0,0 +1,41 @@ +--source include/have_debug.inc +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +--echo *** MDEV-13831: Assertion on event group missing XID/COMMIT event + +--connection slave +--source include/stop_slave.inc +# Use non-GTID mode. In GTID mode, the IO thread will fail if it sees an +# incomplete event group after MDEV-27697 patch. +CHANGE MASTER TO Master_use_gtid= No; +--source include/start_slave.inc + +--connection master +# The dbug injection below is only active in legacy mode. +SET @old_legacy= @@GLOBAL.binlog_legacy_event_pos; +SET GLOBAL binlog_legacy_event_pos= 1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection master1 +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug = '+d,fail_binlog_write_1'; +--error ER_ERROR_ON_WRITE +UPDATE t1 SET a = 2; +SET debug_dbug= @old_dbug; +--error ER_BAD_TABLE_ERROR +DROP TEMPORARY TABLE t1; + +--connection master +CREATE TEMPORARY TABLE t1 (i INT) ENGINE=InnoDB; + +--sync_slave_with_master + +--connection master +SET GLOBAL binlog_legacy_event_pos= @old_legacy; +CALL mtr.add_suppression("Error writing file.*No space left on device"); +DROP TEMPORARY TABLE t1; +DROP TABLE t1; +--source include/rpl_end.inc diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 84da9ab17aa..10cd47bbd62 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -3094,7 +3094,20 @@ static char gtid_begin_string[] = "BEGIN"; int Gtid_log_event::do_apply_event(rpl_group_info *rgi) { + Relay_log_info *rli= rgi->rli; ulonglong bits= thd->variables.option_bits; + + if (unlikely(thd->transaction->all.ha_list || (bits & OPTION_GTID_BEGIN))) + { + rli->report(WARNING_LEVEL, 0, NULL, + "Rolling back unfinished transaction (no COMMIT " + "or ROLLBACK in relay log). This indicates a corrupt binlog " + "on the master, possibly caused by disk full or other write " + "error."); + rgi->cleanup_context(thd, 1); + bits= thd->variables.option_bits; + } + thd->variables.server_id= this->server_id; thd->variables.gtid_domain_id= this->domain_id; thd->variables.gtid_seq_no= this->seq_no; @@ -3113,7 +3126,7 @@ Gtid_log_event::do_apply_event(rpl_group_info *rgi) DBUG_ASSERT((bits & OPTION_GTID_BEGIN) == 0); - Master_info *mi=rgi->rli->mi; + Master_info *mi= rli->mi; switch (flags2 & (FL_DDL | FL_TRANSACTIONAL)) { case FL_TRANSACTIONAL: -- 2.39.5
1 0
0 0
[PATCH] MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION
by Kristian Nielsen 29 Nov '24

29 Nov '24
The partitioning error handling code was looking at thd->lex->alter_info.partition_flags in non-alter-table cases, in which cases the value is stale and contains whatever was set by any earlier ALTER TABLE. This could cause the wrong error code to be generated, which then in some cases can cause replication to break with "different errorcode" error. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- .../suite/rpl/include/rpl_partition.inc | 28 +++++++++++++++++++ .../suite/rpl/r/rpl_partition_archive.result | 18 ++++++++++++ .../suite/rpl/r/rpl_partition_innodb.result | 17 +++++++++++ .../suite/rpl/r/rpl_partition_memory.result | 17 +++++++++++ .../suite/rpl/r/rpl_partition_myisam.result | 17 +++++++++++ sql/ha_partition.cc | 3 +- .../rpl/r/rpl_partition_tokudb.result | 17 +++++++++++ 7 files changed, 116 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/include/rpl_partition.inc b/mysql-test/suite/rpl/include/rpl_partition.inc index 9f16f769f54..509ae2d88a8 100644 --- a/mysql-test/suite/rpl/include/rpl_partition.inc +++ b/mysql-test/suite/rpl/include/rpl_partition.inc @@ -95,6 +95,33 @@ SELECT * FROM test.regular_tbl ORDER BY fkid LIMIT 2; --replace_column 2 date-time 3 USER 4 UUID SELECT * FROM test.regular_tbl ORDER BY fkid DESC LIMIT 2; + +--echo *** MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION +--connection master +eval CREATE TABLE t1 (a INT) +ENGINE=$engine_type +PARTITION BY LIST(a) ( + PARTITION p0 VALUES IN (9, NULL), + PARTITION p1 VALUES IN (8, 2, 7), + PARTITION p2 VALUES IN (6, 4, 5), + PARTITION p3 VALUES IN (3, 1, 0) +); +ALTER TABLE t1 DROP PARTITION p0; + +# This failed statement leaves ALTER_PARTITION_TRUNCATE set in +# thd->lex->alter_info.partition_flags +--error ER_NO_SUCH_TABLE +ALTER TABLE non_existent TRUNCATE PARTITION p1,p2; + +# The bug was that the code would wrongly look at the (now stale) value of +# thd->lex->alter_info.partition_flags and give the wrong error code +# ER_WRONG_PARTITION_NAME. +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +INSERT INTO t1 PARTITION (p1,p2,p3) VALUES (0),(9); + +--sync_slave_with_master + + ###### CLEAN UP SECTION ############## connection master; @@ -102,3 +129,4 @@ DROP PROCEDURE test.proc_norm; DROP PROCEDURE test.proc_byrange; DROP TABLE test.regular_tbl; DROP TABLE test.byrange_tbl; +DROP TABLE test.t1; diff --git a/mysql-test/suite/rpl/r/rpl_partition_archive.result b/mysql-test/suite/rpl/r/rpl_partition_archive.result index 4dfd38bcbc6..5c0374bd5af 100644 --- a/mysql-test/suite/rpl/r/rpl_partition_archive.result +++ b/mysql-test/suite/rpl/r/rpl_partition_archive.result @@ -140,8 +140,26 @@ SELECT * FROM test.regular_tbl ORDER BY fkid DESC LIMIT 2; id dt user uuidf fkid filler 1 date-time USER UUID 300 Partitioned table! Going to test replication for MySQL 2 date-time USER UUID 299 Partitioned table! Going to test replication for MySQL +*** MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION +connection master; +CREATE TABLE t1 (a INT) +ENGINE='Archive' +PARTITION BY LIST(a) ( +PARTITION p0 VALUES IN (9, NULL), +PARTITION p1 VALUES IN (8, 2, 7), +PARTITION p2 VALUES IN (6, 4, 5), +PARTITION p3 VALUES IN (3, 1, 0) +); +ALTER TABLE t1 DROP PARTITION p0; +ALTER TABLE non_existent TRUNCATE PARTITION p1,p2; +ERROR 42S02: Table 'test.non_existent' doesn't exist +INSERT INTO t1 PARTITION (p1,p2,p3) VALUES (0),(9); +ERROR HY000: Table has no partition for value 9 +connection slave; +connection master; DROP PROCEDURE test.proc_norm; DROP PROCEDURE test.proc_byrange; DROP TABLE test.regular_tbl; DROP TABLE test.byrange_tbl; +DROP TABLE test.t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_partition_innodb.result b/mysql-test/suite/rpl/r/rpl_partition_innodb.result index 4b717d8b46c..599d0edf414 100644 --- a/mysql-test/suite/rpl/r/rpl_partition_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_partition_innodb.result @@ -142,9 +142,26 @@ SELECT * FROM test.regular_tbl ORDER BY fkid DESC LIMIT 2; id dt user uuidf fkid filler 1 date-time USER UUID 300 Partitioned table! Going to test replication for MySQL 2 date-time USER UUID 299 Partitioned table! Going to test replication for MySQL +*** MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION +connection master; +CREATE TABLE t1 (a INT) +ENGINE='InnoDB' +PARTITION BY LIST(a) ( +PARTITION p0 VALUES IN (9, NULL), +PARTITION p1 VALUES IN (8, 2, 7), +PARTITION p2 VALUES IN (6, 4, 5), +PARTITION p3 VALUES IN (3, 1, 0) +); +ALTER TABLE t1 DROP PARTITION p0; +ALTER TABLE non_existent TRUNCATE PARTITION p1,p2; +ERROR 42S02: Table 'test.non_existent' doesn't exist +INSERT INTO t1 PARTITION (p1,p2,p3) VALUES (0),(9); +ERROR HY000: Table has no partition for value 9 +connection slave; connection master; DROP PROCEDURE test.proc_norm; DROP PROCEDURE test.proc_byrange; DROP TABLE test.regular_tbl; DROP TABLE test.byrange_tbl; +DROP TABLE test.t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_partition_memory.result b/mysql-test/suite/rpl/r/rpl_partition_memory.result index d37973b0d80..291fdfa33fd 100644 --- a/mysql-test/suite/rpl/r/rpl_partition_memory.result +++ b/mysql-test/suite/rpl/r/rpl_partition_memory.result @@ -142,9 +142,26 @@ SELECT * FROM test.regular_tbl ORDER BY fkid DESC LIMIT 2; id dt user uuidf fkid filler 1 date-time USER UUID 300 Partitioned table! Going to test replication for MySQL 2 date-time USER UUID 299 Partitioned table! Going to test replication for MySQL +*** MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION +connection master; +CREATE TABLE t1 (a INT) +ENGINE='Memory' +PARTITION BY LIST(a) ( +PARTITION p0 VALUES IN (9, NULL), +PARTITION p1 VALUES IN (8, 2, 7), +PARTITION p2 VALUES IN (6, 4, 5), +PARTITION p3 VALUES IN (3, 1, 0) +); +ALTER TABLE t1 DROP PARTITION p0; +ALTER TABLE non_existent TRUNCATE PARTITION p1,p2; +ERROR 42S02: Table 'test.non_existent' doesn't exist +INSERT INTO t1 PARTITION (p1,p2,p3) VALUES (0),(9); +ERROR HY000: Table has no partition for value 9 +connection slave; connection master; DROP PROCEDURE test.proc_norm; DROP PROCEDURE test.proc_byrange; DROP TABLE test.regular_tbl; DROP TABLE test.byrange_tbl; +DROP TABLE test.t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_partition_myisam.result b/mysql-test/suite/rpl/r/rpl_partition_myisam.result index 57c06a7cbec..678548ddb34 100644 --- a/mysql-test/suite/rpl/r/rpl_partition_myisam.result +++ b/mysql-test/suite/rpl/r/rpl_partition_myisam.result @@ -142,9 +142,26 @@ SELECT * FROM test.regular_tbl ORDER BY fkid DESC LIMIT 2; id dt user uuidf fkid filler 1 date-time USER UUID 300 Partitioned table! Going to test replication for MySQL 2 date-time USER UUID 299 Partitioned table! Going to test replication for MySQL +*** MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION +connection master; +CREATE TABLE t1 (a INT) +ENGINE='MyISAM' +PARTITION BY LIST(a) ( +PARTITION p0 VALUES IN (9, NULL), +PARTITION p1 VALUES IN (8, 2, 7), +PARTITION p2 VALUES IN (6, 4, 5), +PARTITION p3 VALUES IN (3, 1, 0) +); +ALTER TABLE t1 DROP PARTITION p0; +ALTER TABLE non_existent TRUNCATE PARTITION p1,p2; +ERROR 42S02: Table 'test.non_existent' doesn't exist +INSERT INTO t1 PARTITION (p1,p2,p3) VALUES (0),(9); +ERROR HY000: Table has no partition for value 9 +connection slave; connection master; DROP PROCEDURE test.proc_norm; DROP PROCEDURE test.proc_byrange; DROP TABLE test.regular_tbl; DROP TABLE test.byrange_tbl; +DROP TABLE test.t1; include/rpl_end.inc diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index ed7fb7fe5f9..e94357f0d45 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -10140,7 +10140,8 @@ void ha_partition::print_error(int error, myf errflag) /* Should probably look for my own errors first */ if ((error == HA_ERR_NO_PARTITION_FOUND) && - ! (thd->lex->alter_info.partition_flags & ALTER_PARTITION_TRUNCATE)) + ! (thd->lex->sql_command == SQLCOM_ALTER_TABLE && + (thd->lex->alter_info.partition_flags & ALTER_PARTITION_TRUNCATE))) { m_part_info->print_no_partition_found(table, errflag); DBUG_VOID_RETURN; diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_partition_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_partition_tokudb.result index 168a5e41b28..e8585e50611 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_partition_tokudb.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_partition_tokudb.result @@ -142,9 +142,26 @@ SELECT * FROM test.regular_tbl ORDER BY fkid DESC LIMIT 2; id dt user uuidf fkid filler 1 date-time USER UUID 300 Partitioned table! Going to test replication for MySQL 2 date-time USER UUID 299 Partitioned table! Going to test replication for MySQL +*** MDEV-5798: Wrong errorcode for missing partition after TRUNCATE PARTITION +connection master; +CREATE TABLE t1 (a INT) +ENGINE=TokuDB; +PARTITION BY LIST(a) ( +PARTITION p0 VALUES IN (9, NULL), +PARTITION p1 VALUES IN (8, 2, 7), +PARTITION p2 VALUES IN (6, 4, 5), +PARTITION p3 VALUES IN (3, 1, 0) +); +ALTER TABLE t1 DROP PARTITION p0; +ALTER TABLE non_existent TRUNCATE PARTITION p1,p2; +ERROR 42S02: Table 'test.non_existent' doesn't exist +INSERT INTO t1 PARTITION (p1,p2,p3) VALUES (0),(9); +ERROR HY000: Table has no partition for value 9 +connection slave; connection master; DROP PROCEDURE test.proc_norm; DROP PROCEDURE test.proc_byrange; DROP TABLE test.regular_tbl; DROP TABLE test.byrange_tbl; +DROP TABLE test.t1; include/rpl_end.inc -- 2.39.5
1 0
0 0
[PATCH] MDEV-11176: FTWRL confusing state about "worker thread pool"
by Kristian Nielsen 29 Nov '24

29 Nov '24
The FLUSH TABLE WITH READ LOCK briefly set the state (in PROCESSLIST) to "Waiting while replication worker thread pool is busy", even if there was nothing to wait for. This is somewhat confusing on a server that might not even have any replication configured, let alone replication workers. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- sql/rpl_parallel.cc | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index b5e1bb96c1e..4d3f12e4116 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -551,6 +551,7 @@ pool_mark_busy(rpl_parallel_thread_pool *pool, THD *thd) { PSI_stage_info old_stage; int res= 0; + bool did_enter_cond= false; /* Wait here while the queue is busy. This is done to make FLUSH TABLES WITH @@ -567,24 +568,28 @@ pool_mark_busy(rpl_parallel_thread_pool *pool, THD *thd) */ DBUG_EXECUTE_IF("mark_busy_mdev_22370",my_sleep(1000000);); mysql_mutex_lock(&pool->LOCK_rpl_thread_pool); - if (thd) - { - thd->set_time_for_next_stage(); - thd->ENTER_COND(&pool->COND_rpl_thread_pool, &pool->LOCK_rpl_thread_pool, - &stage_waiting_for_rpl_thread_pool, &old_stage); - } - while (pool->busy) + if (pool->busy) { - if (thd && unlikely(thd->check_killed())) + if (thd) { - res= 1; - break; + thd->set_time_for_next_stage(); + thd->ENTER_COND(&pool->COND_rpl_thread_pool, &pool->LOCK_rpl_thread_pool, + &stage_waiting_for_rpl_thread_pool, &old_stage); + did_enter_cond= true; } - mysql_cond_wait(&pool->COND_rpl_thread_pool, &pool->LOCK_rpl_thread_pool); + do + { + if (thd && unlikely(thd->check_killed())) + { + res= 1; + break; + } + mysql_cond_wait(&pool->COND_rpl_thread_pool, &pool->LOCK_rpl_thread_pool); + } while (pool->busy); } if (!res) pool->busy= true; - if (thd) + if (did_enter_cond) thd->EXIT_COND(&old_stage); else mysql_mutex_unlock(&pool->LOCK_rpl_thread_pool); -- 2.39.5
1 0
0 0
[PATCH] MDEV-31756: WAIT/NOWAIT in DDL makes binary logs difficult or impossible to replay
by Kristian Nielsen 29 Nov '24

29 Nov '24
Remove any WAIT <n> or NOWAIT option from the query before binlogging DDL. Otherwise applying the event with mysqlbinlog | mysql may fail on NOWAIT if there is temporarily a lock on the table during the apply (while no such lock was there when the original query ran and was binlogged). Such locks can occur even without user control, since InnoDB background tasks can sometimes hold such locks for a short while. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- .../suite/binlog/r/binlog_ddl_nowait.result | 64 +++++++++++++++ .../suite/binlog/t/binlog_ddl_nowait.test | 77 +++++++++++++++++++ sql/sql_lex.cc | 26 +++++-- sql/sql_lex.h | 19 +++++ sql/sql_table.cc | 57 +++++++++++++- sql/sql_yacc.yy | 62 ++++++++++++--- 6 files changed, 286 insertions(+), 19 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_ddl_nowait.result create mode 100644 mysql-test/suite/binlog/t/binlog_ddl_nowait.test diff --git a/mysql-test/suite/binlog/r/binlog_ddl_nowait.result b/mysql-test/suite/binlog/r/binlog_ddl_nowait.result new file mode 100644 index 00000000000..86712fb533a --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_ddl_nowait.result @@ -0,0 +1,64 @@ +*** MDEV-31756: WAIT/NOWAIT in DDL makes binary logs difficult or impossible to replay +connection default; +RESET MASTER; +CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM; +ALTER TABLE t1 WAIT +0.0 ADD b INT; +ALTER TABLE t1 WAIT +4.3 ADD c INT; +INSERT INTO t1(a,b) VALUES (1,1), (2,1), (3,2), (4,3), (5, 5), (6, 8), (7, 13); +CREATE INDEX b_idx ON t1(b) WAIT 0; +OPTIMIZE TABLE t1 NOWAIT; +Table Op Msg_type Msg_text +test.t1 optimize status OK +TRUNCATE TABLE t1 NOWAIT; +DROP INDEX b_idx ON t1 WAIT 0; +RENAME TABLE t1 NOWAIT TO t2; +DROP TABLE t2 WAIT 1; +connection default; +FLUSH BINARY LOGS; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +connect con1,localhost,root,,; +INSERT INTO t1 VALUES (0*SLEEP(0.2)); +connection default; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +connection con1; +INSERT INTO t1(a) VALUES (0*SLEEP(0.2) + 100); +connection default; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `b_idx` (`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +connection con1; +INSERT INTO t1(a) VALUES (0*SLEEP(0.2) + 200); +connection default; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +connection con1; +disconnect con1; +connection default; +NOT FOUND /WAIT/ in mdev31756.text +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_ddl_nowait.test b/mysql-test/suite/binlog/t/binlog_ddl_nowait.test new file mode 100644 index 00000000000..b2b5a4ec2b6 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_ddl_nowait.test @@ -0,0 +1,77 @@ +# DDL binlogging is the same regardless of binlog format +--source include/have_binlog_format_mixed.inc + +--echo *** MDEV-31756: WAIT/NOWAIT in DDL makes binary logs difficult or impossible to replay + +--connection default +--let $datadir= `select @@datadir` +RESET MASTER; + +--let $file= query_get_value(SHOW MASTER STATUS, File, 1) +--let $pos0= query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM; +--let $pos1= query_get_value(SHOW MASTER STATUS, Position, 1) +ALTER TABLE t1 WAIT +0.0 ADD b INT; +ALTER TABLE t1 WAIT +4.3 ADD c INT; +INSERT INTO t1(a,b) VALUES (1,1), (2,1), (3,2), (4,3), (5, 5), (6, 8), (7, 13); +--let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE INDEX b_idx ON t1(b) WAIT 0; +OPTIMIZE TABLE t1 NOWAIT; +TRUNCATE TABLE t1 NOWAIT; +--let $pos3= query_get_value(SHOW MASTER STATUS, Position, 1) +DROP INDEX b_idx ON t1 WAIT 0; +--let $pos4= query_get_value(SHOW MASTER STATUS, Position, 1) +RENAME TABLE t1 NOWAIT TO t2; +DROP TABLE t2 WAIT 1; + + +# Test that we can mysqlbinlog|mysql the DDL even though it has to wait for +# the table lock for a short while. +# +# This is very prone to races of course, but that is ok. The case we want to +# test is when mysqbinlog|mysql runs while the table lock is held, and that +# will be the case "most" of the time. If we race and the lock is not held, +# it just means the test is ineffective, it will still pass. + +--connection default +FLUSH BINARY LOGS; +--exec $MYSQL_BINLOG --start-position=$pos0 --stop-position=$pos1 $datadir/master-bin.000001 | $MYSQL test +SHOW CREATE TABLE t1; + +connect (con1,localhost,root,,); +send INSERT INTO t1 VALUES (0*SLEEP(0.2)); + +--connection default +--exec $MYSQL_BINLOG --start-position=$pos1 --stop-position=$pos2 $datadir/master-bin.000001 | $MYSQL test +SHOW CREATE TABLE t1; + +--connection con1 +reap; +send INSERT INTO t1(a) VALUES (0*SLEEP(0.2) + 100); + +--connection default +--exec $MYSQL_BINLOG --start-position=$pos2 --stop-position=$pos3 $datadir/master-bin.000001 | $MYSQL test +SHOW CREATE TABLE t1; + +--connection con1 +reap; +send INSERT INTO t1(a) VALUES (0*SLEEP(0.2) + 200); + +--connection default +--exec $MYSQL_BINLOG --start-position=$pos3 --stop-position=$pos4 $datadir/master-bin.000001 | $MYSQL test +SHOW CREATE TABLE t1; + +--connection con1 +reap; +--disconnect con1 +--connection default + +# Check that there is no WAIT <n> or NOWAIT in binlogged queries. +--exec $MYSQL_BINLOG $datadir/master-bin.000001 >$MYSQL_TMP_DIR/mdev31756.text +--let SEARCH_FILE= $MYSQL_TMP_DIR/mdev31756.text +--let SEARCH_PATTERN= WAIT +--let SEARCH_ABORT= FOUND +--source include/search_pattern_in_file.inc +--remove_file $MYSQL_TMP_DIR/mdev31756.text + +DROP TABLE t1; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0131068a530..75ec0d9dffe 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1557,6 +1557,19 @@ LEX_CSTRING Lex_input_stream::get_token(uint skip, uint length) } +Lex_string_with_pos_st +Lex_input_stream::get_token_with_pos(uint skip, uint length) +{ + LEX_CSTRING tmp; + Lex_string_with_pos_st out; + out.start_pos= m_tok_start + skip - get_buf(); + tmp= get_token(skip, length); + out.str= tmp.str; + out.length= tmp.length; + return out; +} + + static size_t my_unescape(CHARSET_INFO *cs, char *to, const char *str, const char *end, int sep, bool backslash_escapes) @@ -2193,7 +2206,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) if ((yyLength() >= 3) && !ident_map[c]) { /* skip '0x' */ - yylval->lex_str= get_token(2, yyLength() - 2); + yylval->lex_str_with_pos= get_token_with_pos(2, yyLength() - 2); return (HEX_NUM); } yyUnget(); @@ -2233,7 +2246,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) { yySkip(); while (my_isdigit(cs, yyGet())) ; - yylval->lex_str= get_token(0, yyLength()); + yylval->lex_str_with_pos= get_token_with_pos(0, yyLength()); return(FLOAT_NUM); } } @@ -2272,8 +2285,9 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) - the number is either not followed by a dot at all, or - the number is followed by a double dot as in: FOR i IN 1..10 */ - yylval->lex_str= get_token(0, yyLength()); - return int_token(yylval->lex_str.str, (uint) yylval->lex_str.length); + yylval->lex_str_with_pos= get_token_with_pos(0, yyLength()); + return int_token(yylval->lex_str_with_pos.str, + (uint) yylval->lex_str_with_pos.length); } // fall through case MY_LEX_REAL: // Incomplete real number @@ -2287,10 +2301,10 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) if (!my_isdigit(cs, c)) return ABORT_SYM; // No digit after sign while (my_isdigit(cs, yyGet())) ; - yylval->lex_str= get_token(0, yyLength()); + yylval->lex_str_with_pos= get_token_with_pos(0, yyLength()); return(FLOAT_NUM); } - yylval->lex_str= get_token(0, yyLength()); + yylval->lex_str_with_pos= get_token_with_pos(0, yyLength()); return(DECIMAL_NUM); case MY_LEX_HEX_NUMBER: // Found x'hexstring' diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 780ad3d9e16..0c17480bf3b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -103,6 +103,12 @@ struct Lex_string_with_metadata_st: public LEX_CSTRING }; +struct Lex_string_with_pos_st: public LEX_CSTRING +{ + uint start_pos; +}; + + /* Used to store identifiers in the client character set. Points to a query fragment. @@ -2863,6 +2869,7 @@ class Lex_input_stream int find_keyword(Lex_ident_cli_st *str, uint len, bool function) const; int find_keyword_qualified_special_func(Lex_ident_cli_st *str, uint len) const; LEX_CSTRING get_token(uint skip, uint length); + Lex_string_with_pos_st get_token_with_pos(uint skip, uint length); int scan_ident_start(THD *thd, Lex_ident_cli_st *str); int scan_ident_middle(THD *thd, Lex_ident_cli_st *str, CHARSET_INFO **cs, my_lex_states *); @@ -3540,6 +3547,12 @@ struct LEX: public Query_tables_list */ uint table_count_update; + /* + Used to remember a character position during parsing, eg. the end of + ulong_num for ddl_wait_nowait_end_offset. + */ + uint last_lex_end_pos; + uint8 describe; /* A flag that indicates what kinds of derived tables are present in the @@ -3585,15 +3598,21 @@ struct LEX: public Query_tables_list keyword_delayed_begin_offset is the offset to the beginning of the DELAYED keyword in INSERT DELAYED statement. keyword_delayed_end_offset is the offset to the character right after the DELAYED keyword. + + Similarly, ddl_wait_nowait_begin_offset and ddl_wait_nowait_end_offset mark + the start and end of the "NOWAIT" or "WAIT <number>" (including last + character of <number>) option for ALTER TABLE and similar statements. */ union { const char *stmt_definition_begin; uint keyword_delayed_begin_offset; + uint ddl_wait_nowait_begin_offset; }; union { const char *stmt_definition_end; uint keyword_delayed_end_offset; + uint ddl_wait_nowait_end_offset; }; /** diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 748ae999087..a007f7689e6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -996,6 +996,23 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) } +/** + Create a new query string for DDL with the WAIT <n> or NOWAIT option removed. + This option should not be in the binlog, as a query that succeeded on the + master _must_ also succeed on the slave, even if it needs to wait. +*/ +static int +create_stmt_without_nowait(THD *thd, String *buf) +{ + if (buf->append(thd->query(), thd->query_length()) || + buf->replace(thd->lex->ddl_wait_nowait_begin_offset, + thd->lex->ddl_wait_nowait_end_offset - + thd->lex->ddl_wait_nowait_begin_offset, NULL, 0)) + return 1; + return 0; +} + + /* SYNOPSIS write_bin_log() @@ -1035,9 +1052,43 @@ int write_bin_log(THD *thd, bool clear_error, } else errcode= query_error_code(thd, TRUE); - error= thd->binlog_query(THD::STMT_QUERY_TYPE, - query, query_length, is_trans, FALSE, FALSE, - errcode) > 0; + + /* Remove any NOWAIT or WAIT <n> from DDL. */ + String log_query; + switch(thd->lex->sql_command) + { + case SQLCOM_TRUNCATE: + case SQLCOM_DROP_INDEX: + case SQLCOM_RENAME_TABLE: + case SQLCOM_OPTIMIZE: + case SQLCOM_ALTER_TABLE: + case SQLCOM_CREATE_INDEX: + /* DROP TABLE is binlogged with a rewritten query, so omitted here. */ + if (thd->lex->ddl_wait_nowait_begin_offset > 0) + { + if (create_stmt_without_nowait(thd, &log_query)) + { + sql_print_error("Event Error: An error occurred while creating query " + "string for DDL with NOWAIT/WAIT removed, before " + "writing it into binary log."); + error= 1; + } + else + { + query= log_query.c_ptr(); + query_length= log_query.length(); + } + } + break; + + default: + ; /* Nothing */ + } + + if (!error) + error= thd->binlog_query(THD::STMT_QUERY_TYPE, + query, query_length, is_trans, FALSE, FALSE, + errcode) > 0; thd_proc_info(thd, 0); } return error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 85717713325..75be19cb4c8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -201,6 +201,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)() /* structs */ LEX_CSTRING lex_str; + Lex_string_with_pos_st lex_str_with_pos; Lex_ident_cli_st kwd; Lex_ident_cli_st ident_cli; Lex_ident_sys_st ident_sys; @@ -1316,9 +1317,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %right INTO %type <lex_str> - DECIMAL_NUM FLOAT_NUM NUM LONG_NUM - HEX_NUM HEX_STRING - LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text + HEX_STRING + LEX_HOSTNAME field_ident select_alias ident_or_text TEXT_STRING_sys TEXT_STRING_literal key_cache_name sp_opt_label BIN_NUM TEXT_STRING_filesystem @@ -1326,6 +1326,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); sp_block_label sp_control_label opt_place opt_db udt_name +%type <lex_str_with_pos> + DECIMAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM ULONGLONG_NUM + %type <ident_sys> IDENT_sys ident_func @@ -12747,12 +12750,41 @@ int_num: ; ulong_num: - opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } - | HEX_NUM { $$= strtoul($1.str, (char**) 0, 16); } - | opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } - | opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } - | opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } - | opt_plus FLOAT_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } + opt_plus NUM + { + int error; + $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); + Lex->last_lex_end_pos= $2.start_pos + (uint)$2.length; + } + | HEX_NUM + { + $$= strtoul($1.str, (char**) 0, 16); + Lex->last_lex_end_pos= $1.start_pos + (uint)$1.length; + } + | opt_plus LONG_NUM + { + int error; + $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); + Lex->last_lex_end_pos= $2.start_pos + (uint)$2.length; + } + | opt_plus ULONGLONG_NUM + { + int error; + $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); + Lex->last_lex_end_pos= $2.start_pos + (uint)$2.length; + } + | opt_plus DECIMAL_NUM + { + int error; + $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); + Lex->last_lex_end_pos= $2.start_pos + (uint)$2.length; + } + | opt_plus FLOAT_NUM + { + int error; + $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); + Lex->last_lex_end_pos= $2.start_pos + (uint)$2.length; + } ; real_ulong_num: @@ -17116,15 +17148,25 @@ lock: opt_lock_wait_timeout: /* empty */ - {} + { + LEX *lex= Lex; + lex->ddl_wait_nowait_begin_offset= 0; + lex->ddl_wait_nowait_end_offset= 0; + } | WAIT_SYM ulong_num { + LEX *lex= Lex; + lex->ddl_wait_nowait_begin_offset= (uint)($1.pos() - thd->query()); + lex->ddl_wait_nowait_end_offset= lex->last_lex_end_pos; if (unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("lock_wait_timeout"), $2)) || unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("innodb_lock_wait_timeout"), $2))) MYSQL_YYABORT; } | NOWAIT_SYM { + LEX *lex= Lex; + lex->ddl_wait_nowait_begin_offset= (uint)($1.pos() - thd->query()); + lex->ddl_wait_nowait_end_offset= (uint)($1.end() - thd->query()); if (unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("lock_wait_timeout"), 0)) || unlikely(set_statement_var_if_exists(thd, STRING_WITH_LEN("innodb_lock_wait_timeout"), 0))) MYSQL_YYABORT; -- 2.39.5
1 0
0 0
[PATCH] MDEV-31761: mariadb-binlog prints fractional timestamp part incorrectly
by Kristian Nielsen 28 Nov '24

28 Nov '24
Fractional part < 100000 microseconds was printed without leading zeros, causing such timestamps to be applied incorrectly in mariadb-binlog | mysql Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- mysql-test/main/mysqlbinlog.result | 26 ++++++++++++++++++++++++ mysql-test/main/mysqlbinlog.test | 32 ++++++++++++++++++++++++++++++ sql/log_event_client.cc | 7 +++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/mysqlbinlog.result b/mysql-test/main/mysqlbinlog.result index c6d9ef97229..76ded3d31f8 100644 --- a/mysql-test/main/mysqlbinlog.result +++ b/mysql-test/main/mysqlbinlog.result @@ -1286,3 +1286,29 @@ ERROR: Bad syntax in rewrite-db: empty FROM db ERROR: Bad syntax in rewrite-db: empty FROM db +# +# MDEV-31761: Timestamp is written into binary log incorrectly +# +SET SESSION binlog_format= MIXED; +RESET MASTER; +CREATE TABLE t (a INT, +b TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)); +set SESSION timestamp= 1689978980.012345; +INSERT INTO t (a) VALUES (1); +SELECT * from t; +a b +1 2023-07-22 00:36:20.012345 +FLUSH BINARY LOGS; +SET SESSION timestamp= 1689978980.567890; +SET SESSION binlog_format= ROW; +UPDATE t SET a = 2; +FLUSH BINARY LOGS; +SET SESSION binlog_format= STATEMENT; +DROP TABLE t; +SELECT * FROM t; +a b +1 2023-07-22 00:36:20.012345 +SELECT * FROM t; +a b +2 2023-07-22 00:36:20.567890 +DROP TABLE t; diff --git a/mysql-test/main/mysqlbinlog.test b/mysql-test/main/mysqlbinlog.test index 22a85393a35..1747d55d29d 100644 --- a/mysql-test/main/mysqlbinlog.test +++ b/mysql-test/main/mysqlbinlog.test @@ -637,3 +637,35 @@ FLUSH LOGS; --exec $MYSQL_BINLOG --rewrite-db=" ->" --short-form $MYSQLD_DATADIR/master-bin.000001 2>&1 --exec $MYSQL_BINLOG --rewrite-db=" test -> foo " --short-form $MYSQLD_DATADIR/master-bin.000001 > /dev/null 2> $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn + + +--echo # +--echo # MDEV-31761: Timestamp is written into binary log incorrectly +--echo # + +SET SESSION binlog_format= MIXED; + +RESET MASTER; +CREATE TABLE t (a INT, + b TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)); +set SESSION timestamp= 1689978980.012345; +INSERT INTO t (a) VALUES (1); +SELECT * from t; +FLUSH BINARY LOGS; +SET SESSION timestamp= 1689978980.567890; +SET SESSION binlog_format= ROW; +UPDATE t SET a = 2; +FLUSH BINARY LOGS; +SET SESSION binlog_format= STATEMENT; + +# Replay to see that timestamps are applied correctly. +# The bug was that leading zeros on the fractional part were not included in +# the mysqlbinlog output, so 1689978980.012345 was applied as 1689978980.12345. + +DROP TABLE t; +--let $datadir= `select @@datadir` +--exec $MYSQL_BINLOG $datadir/master-bin.000001 | $MYSQL test +SELECT * FROM t; +--exec $MYSQL_BINLOG $datadir/master-bin.000002 | $MYSQL test +SELECT * FROM t; +DROP TABLE t; diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index 11fabbbca39..720cc5ab611 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -1851,8 +1851,11 @@ bool Query_log_event::print_query_header(IO_CACHE* file, end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); if (when_sec_part && when_sec_part <= TIME_MAX_SECOND_PART) { - *end++= '.'; - end=int10_to_str(when_sec_part, end, 10); + char buff2[1 + 6 + 1]; + /* Ensure values < 100000 are printed with leading zeros, MDEV-31761. */ + snprintf(buff2, sizeof(buff2), ".%06lu", when_sec_part); + DBUG_ASSERT(strlen(buff2) == 1 + 6); + end= strmov(end, buff2); } end= strmov(end, print_event_info->delimiter); *end++='\n'; -- 2.39.5
1 0
0 0
[PATCH] Restore the THD state correctly in parallel replication
by Kristian Nielsen 28 Nov '24

28 Nov '24
If both do_gco_wait() and do_ftwrl_wait() had to wait, the state was not restored correctly. Signed-off-by: Kristian Nielsen <knielsen(a)knielsen-hq.org> --- sql/rpl_parallel.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index e59c1de7a7c..553557638f6 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -500,7 +500,8 @@ do_ftwrl_wait(rpl_group_info *rgi, { thd->set_time_for_next_stage(); thd->ENTER_COND(&entry->COND_parallel_entry, &entry->LOCK_parallel_entry, - &stage_waiting_for_ftwrl, old_stage); + &stage_waiting_for_ftwrl, + (*did_enter_cond ? nullptr : old_stage)); *did_enter_cond= true; do { -- 2.39.5
1 0
0 0

HyperKitty Powered by HyperKitty version 1.3.12.