Commit 1766a18e authored by Vlad Lesin's avatar Vlad Lesin

MDEV-19577 Replication does not work with innodb_autoinc_lock_mode=2

The first step for deprecating innodb_autoinc_lock_mode(see MDEV-27844) is:
- to switch statement binlog format to ROW if binlog format is MIXED and
the statement changes autoincremented fields
- issue warnings if innodb_autoinc_lock_mode == 2 and binlog format is
STATEMENT
parent e7cf871d
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
select @@innodb_autoinc_lock_mode;
@@innodb_autoinc_lock_mode
2
select @@binlog_format;
@@binlog_format
MIXED
create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB;
insert into t1 values (NULL,1);
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `mtr`; INSERT INTO test_suppressions (pattern) VALUES ( NAME_CONST('pattern',_latin1'Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT' COLLATE 'latin1_swedish_ci'))
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Annotate_rows # # insert into t1 values (NULL,1)
master-bin.000001 # Table_map # # table_id: # (test.t1)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000001 # Xid # # COMMIT /* XID */
set global binlog_format=STATEMENT;
connect con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK;
insert into t1 values (NULL,1);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
insert into t1 values (NULL,1);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave
disconnect con1;
connection default;
set global binlog_format=MIXED;
DROP TABLE t1;
--source include/have_innodb.inc
--source include/have_binlog_format_mixed.inc
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
select @@innodb_autoinc_lock_mode;
select @@binlog_format;
create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB;
insert into t1 values (NULL,1);
--source include/show_binlog_events.inc
set global binlog_format=STATEMENT;
--connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK)
insert into t1 values (NULL,1);
insert into t1 values (NULL,1);
--disconnect con1
--connection default
set global binlog_format=MIXED;
DROP TABLE t1;
...@@ -4668,6 +4668,11 @@ class handler :public Sql_alloc ...@@ -4668,6 +4668,11 @@ class handler :public Sql_alloc
const uchar *pack_frm_data, const uchar *pack_frm_data,
size_t pack_frm_len) size_t pack_frm_len)
{ return HA_ERR_WRONG_COMMAND; } { return HA_ERR_WRONG_COMMAND; }
/* @return true if it's necessary to switch current statement log format from
STATEMENT to ROW if binary log format is MIXED and autoincrement values
are changed in the statement */
virtual bool autoinc_lock_mode_stmt_unsafe() const
{ return false; }
virtual int drop_partitions(const char *path) virtual int drop_partitions(const char *path)
{ return HA_ERR_WRONG_COMMAND; } { return HA_ERR_WRONG_COMMAND; }
virtual int rename_partitions(const char *path) virtual int rename_partitions(const char *path)
......
...@@ -6079,6 +6079,10 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -6079,6 +6079,10 @@ int THD::decide_logging_format(TABLE_LIST *tables)
bool is_write= FALSE; // If any write tables bool is_write= FALSE; // If any write tables
bool has_read_tables= FALSE; // If any read only tables bool has_read_tables= FALSE; // If any read only tables
bool has_auto_increment_write_tables= FALSE; // Write with auto-increment bool has_auto_increment_write_tables= FALSE; // Write with auto-increment
/* true if it's necessary to switch current statement log format from
STATEMENT to ROW if binary log format is MIXED and autoincrement values
are changed in the statement */
bool has_unsafe_stmt_autoinc_lock_mode= false;
/* If a write table that doesn't have auto increment part first */ /* If a write table that doesn't have auto increment part first */
bool has_write_table_auto_increment_not_first_in_pk= FALSE; bool has_write_table_auto_increment_not_first_in_pk= FALSE;
bool has_auto_increment_write_tables_not_first= FALSE; bool has_auto_increment_write_tables_not_first= FALSE;
...@@ -6200,6 +6204,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -6200,6 +6204,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
has_auto_increment_write_tables_not_first= found_first_not_own_table; has_auto_increment_write_tables_not_first= found_first_not_own_table;
if (share->next_number_keypart != 0) if (share->next_number_keypart != 0)
has_write_table_auto_increment_not_first_in_pk= true; has_write_table_auto_increment_not_first_in_pk= true;
has_unsafe_stmt_autoinc_lock_mode=
table->file->autoinc_lock_mode_stmt_unsafe();
} }
} }
...@@ -6268,6 +6274,9 @@ int THD::decide_logging_format(TABLE_LIST *tables) ...@@ -6268,6 +6274,9 @@ int THD::decide_logging_format(TABLE_LIST *tables)
if (has_write_tables_with_unsafe_statements) if (has_write_tables_with_unsafe_statements)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
if (has_unsafe_stmt_autoinc_lock_mode)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_LOCK_MODE);
/* /*
A query that modifies autoinc column in sub-statement can make the A query that modifies autoinc column in sub-statement can make the
master and slave inconsistent. master and slave inconsistent.
......
...@@ -75,7 +75,14 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = ...@@ -75,7 +75,14 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC, ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC,
ER_BINLOG_UNSAFE_UPDATE_IGNORE, ER_BINLOG_UNSAFE_UPDATE_IGNORE,
ER_BINLOG_UNSAFE_INSERT_TWO_KEYS, ER_BINLOG_UNSAFE_INSERT_TWO_KEYS,
ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST,
/*
There is no need to add new error code as we plan to get rid of auto
increment lock mode variable, so we use existing error code below, add
the correspondent text to the existing error message during merging to
non-GA release.
*/
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
}; };
......
...@@ -1740,6 +1740,11 @@ class Query_tables_list ...@@ -1740,6 +1740,11 @@ class Query_tables_list
*/ */
BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST, BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST,
/**
Autoincrement lock mode is incompatible with STATEMENT binlog format.
*/
BINLOG_STMT_UNSAFE_AUTOINC_LOCK_MODE,
/* The last element of this enumeration type. */ /* The last element of this enumeration type. */
BINLOG_STMT_UNSAFE_COUNT BINLOG_STMT_UNSAFE_COUNT
}; };
......
...@@ -9594,6 +9594,14 @@ ha_innobase::change_active_index( ...@@ -9594,6 +9594,14 @@ ha_innobase::change_active_index(
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* @return true if it's necessary to switch current statement log format from
STATEMENT to ROW if binary log format is MIXED and autoincrement values
are changed in the statement */
bool ha_innobase::autoinc_lock_mode_stmt_unsafe() const
{
return innobase_autoinc_lock_mode == AUTOINC_NO_LOCKING;
}
/***********************************************************************//** /***********************************************************************//**
Reads the next or previous row from a cursor, which must have previously been Reads the next or previous row from a cursor, which must have previously been
positioned using index_read. positioned using index_read.
......
...@@ -448,6 +448,10 @@ class ha_innobase: public handler ...@@ -448,6 +448,10 @@ class ha_innobase: public handler
int general_fetch(uchar* buf, uint direction, uint match_mode); int general_fetch(uchar* buf, uint direction, uint match_mode);
int change_active_index(uint keynr); int change_active_index(uint keynr);
/* @return true if it's necessary to switch current statement log
format from STATEMENT to ROW if binary log format is MIXED and
autoincrement values are changed in the statement */
bool autoinc_lock_mode_stmt_unsafe() const;
dict_index_t* innobase_get_index(uint keynr); dict_index_t* innobase_get_index(uint keynr);
#ifdef WITH_WSREP #ifdef WITH_WSREP
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment