Skip to content

Commit 1766a18

Browse files
committed
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
1 parent e7cf871 commit 1766a18

File tree

9 files changed

+94
-1
lines changed

9 files changed

+94
-1
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
2+
select @@innodb_autoinc_lock_mode;
3+
@@innodb_autoinc_lock_mode
4+
2
5+
select @@binlog_format;
6+
@@binlog_format
7+
MIXED
8+
create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB;
9+
insert into t1 values (NULL,1);
10+
include/show_binlog_events.inc
11+
Log_name Pos Event_type Server_id End_log_pos Info
12+
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
13+
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'))
14+
master-bin.000001 # Query # # COMMIT
15+
master-bin.000001 # Gtid # # GTID #-#-#
16+
master-bin.000001 # Query # # use `test`; create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB
17+
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
18+
master-bin.000001 # Annotate_rows # # insert into t1 values (NULL,1)
19+
master-bin.000001 # Table_map # # table_id: # (test.t1)
20+
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
21+
master-bin.000001 # Xid # # COMMIT /* XID */
22+
set global binlog_format=STATEMENT;
23+
connect con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK;
24+
insert into t1 values (NULL,1);
25+
Warnings:
26+
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
27+
insert into t1 values (NULL,1);
28+
Warnings:
29+
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
30+
disconnect con1;
31+
connection default;
32+
set global binlog_format=MIXED;
33+
DROP TABLE t1;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--innodb_autoinc_lock_mode=2
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--source include/have_innodb.inc
2+
--source include/have_binlog_format_mixed.inc
3+
4+
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
5+
6+
select @@innodb_autoinc_lock_mode;
7+
select @@binlog_format;
8+
9+
create table t1 (a int not null auto_increment,b int, primary key (a)) engine=InnoDB;
10+
insert into t1 values (NULL,1);
11+
--source include/show_binlog_events.inc
12+
13+
set global binlog_format=STATEMENT;
14+
--connect (con1,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK)
15+
insert into t1 values (NULL,1);
16+
insert into t1 values (NULL,1);
17+
--disconnect con1
18+
--connection default
19+
20+
set global binlog_format=MIXED;
21+
DROP TABLE t1;

sql/handler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4668,6 +4668,11 @@ class handler :public Sql_alloc
46684668
const uchar *pack_frm_data,
46694669
size_t pack_frm_len)
46704670
{ return HA_ERR_WRONG_COMMAND; }
4671+
/* @return true if it's necessary to switch current statement log format from
4672+
STATEMENT to ROW if binary log format is MIXED and autoincrement values
4673+
are changed in the statement */
4674+
virtual bool autoinc_lock_mode_stmt_unsafe() const
4675+
{ return false; }
46714676
virtual int drop_partitions(const char *path)
46724677
{ return HA_ERR_WRONG_COMMAND; }
46734678
virtual int rename_partitions(const char *path)

sql/sql_class.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6079,6 +6079,10 @@ int THD::decide_logging_format(TABLE_LIST *tables)
60796079
bool is_write= FALSE; // If any write tables
60806080
bool has_read_tables= FALSE; // If any read only tables
60816081
bool has_auto_increment_write_tables= FALSE; // Write with auto-increment
6082+
/* true if it's necessary to switch current statement log format from
6083+
STATEMENT to ROW if binary log format is MIXED and autoincrement values
6084+
are changed in the statement */
6085+
bool has_unsafe_stmt_autoinc_lock_mode= false;
60826086
/* If a write table that doesn't have auto increment part first */
60836087
bool has_write_table_auto_increment_not_first_in_pk= FALSE;
60846088
bool has_auto_increment_write_tables_not_first= FALSE;
@@ -6200,6 +6204,8 @@ int THD::decide_logging_format(TABLE_LIST *tables)
62006204
has_auto_increment_write_tables_not_first= found_first_not_own_table;
62016205
if (share->next_number_keypart != 0)
62026206
has_write_table_auto_increment_not_first_in_pk= true;
6207+
has_unsafe_stmt_autoinc_lock_mode=
6208+
table->file->autoinc_lock_mode_stmt_unsafe();
62036209
}
62046210
}
62056211

@@ -6268,6 +6274,9 @@ int THD::decide_logging_format(TABLE_LIST *tables)
62686274
if (has_write_tables_with_unsafe_statements)
62696275
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
62706276

6277+
if (has_unsafe_stmt_autoinc_lock_mode)
6278+
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_LOCK_MODE);
6279+
62716280
/*
62726281
A query that modifies autoinc column in sub-statement can make the
62736282
master and slave inconsistent.

sql/sql_lex.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,14 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
7575
ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC,
7676
ER_BINLOG_UNSAFE_UPDATE_IGNORE,
7777
ER_BINLOG_UNSAFE_INSERT_TWO_KEYS,
78-
ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST
78+
ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST,
79+
/*
80+
There is no need to add new error code as we plan to get rid of auto
81+
increment lock mode variable, so we use existing error code below, add
82+
the correspondent text to the existing error message during merging to
83+
non-GA release.
84+
*/
85+
ER_BINLOG_UNSAFE_SYSTEM_VARIABLE
7986
};
8087

8188

sql/sql_lex.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,11 @@ class Query_tables_list
17401740
*/
17411741
BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST,
17421742

1743+
/**
1744+
Autoincrement lock mode is incompatible with STATEMENT binlog format.
1745+
*/
1746+
BINLOG_STMT_UNSAFE_AUTOINC_LOCK_MODE,
1747+
17431748
/* The last element of this enumeration type. */
17441749
BINLOG_STMT_UNSAFE_COUNT
17451750
};

storage/innobase/handler/ha_innodb.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9594,6 +9594,14 @@ ha_innobase::change_active_index(
95949594
DBUG_RETURN(0);
95959595
}
95969596

9597+
/* @return true if it's necessary to switch current statement log format from
9598+
STATEMENT to ROW if binary log format is MIXED and autoincrement values
9599+
are changed in the statement */
9600+
bool ha_innobase::autoinc_lock_mode_stmt_unsafe() const
9601+
{
9602+
return innobase_autoinc_lock_mode == AUTOINC_NO_LOCKING;
9603+
}
9604+
95979605
/***********************************************************************//**
95989606
Reads the next or previous row from a cursor, which must have previously been
95999607
positioned using index_read.

storage/innobase/handler/ha_innodb.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ class ha_innobase: public handler
448448

449449
int general_fetch(uchar* buf, uint direction, uint match_mode);
450450
int change_active_index(uint keynr);
451+
/* @return true if it's necessary to switch current statement log
452+
format from STATEMENT to ROW if binary log format is MIXED and
453+
autoincrement values are changed in the statement */
454+
bool autoinc_lock_mode_stmt_unsafe() const;
451455
dict_index_t* innobase_get_index(uint keynr);
452456

453457
#ifdef WITH_WSREP

0 commit comments

Comments
 (0)