1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

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
This commit is contained in:
Vlad Lesin
2022-03-02 21:29:53 +03:00
parent e7cf871dda
commit 1766a18e06
9 changed files with 94 additions and 1 deletions

View File

@ -0,0 +1,33 @@
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;

View File

@ -0,0 +1 @@
--innodb_autoinc_lock_mode=2

View File

@ -0,0 +1,21 @@
--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;

View File

@ -4668,6 +4668,11 @@ public:
const uchar *pack_frm_data,
size_t pack_frm_len)
{ 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)
{ return HA_ERR_WRONG_COMMAND; }
virtual int rename_partitions(const char *path)

View File

@ -6079,6 +6079,10 @@ int THD::decide_logging_format(TABLE_LIST *tables)
bool is_write= FALSE; // If any write tables
bool has_read_tables= FALSE; // If any read only tables
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 */
bool has_write_table_auto_increment_not_first_in_pk= FALSE;
bool has_auto_increment_write_tables_not_first= FALSE;
@ -6200,6 +6204,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
has_auto_increment_write_tables_not_first= found_first_not_own_table;
if (share->next_number_keypart != 0)
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)
if (has_write_tables_with_unsafe_statements)
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
master and slave inconsistent.

View File

@ -75,7 +75,14 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC,
ER_BINLOG_UNSAFE_UPDATE_IGNORE,
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
};

View File

@ -1740,6 +1740,11 @@ public:
*/
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. */
BINLOG_STMT_UNSAFE_COUNT
};

View File

@ -9594,6 +9594,14 @@ ha_innobase::change_active_index(
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
positioned using index_read.

View File

@ -448,6 +448,10 @@ protected:
int general_fetch(uchar* buf, uint direction, uint match_mode);
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);
#ifdef WITH_WSREP