1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

BUG#33029 5.0 to 5.1 replication fails on dup key when inserting

using a trig in SP

For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.

Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.

Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement.  When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.

The patch for 5.0 fixed it not to generate the erroneous Intvar
event, another patch for 5.1 fixed it to ignore the SET INSERT_ID
value when executing functions/triggers if it is replicating from
a master of buggy versions.


mysql-test/include/show_binlog_events.inc:
  add $binlog_start parameter to set the start position when show binlog events, if not set a default value will be used.
  
  mask out column 2(Pos), 4(Server_id), table_id, and file_id
sql/sql_class.cc:
  Reset insert_id_used after each query in SP
mysql-test/r/rpl_auto_increment_bug33029.result:
  Add test for bug33029, test if the master generate the erroneous event or not
mysql-test/t/rpl_auto_increment_bug33029.test:
  Add test for bug33029, test if the master generate the erroneous event or not
This commit is contained in:
unknown
2008-03-14 10:03:01 +08:00
parent 0946b1d2a7
commit d5f09a13de
4 changed files with 290 additions and 3 deletions

View File

@ -0,0 +1,167 @@
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
DROP TABLE IF EXISTS t1, t2;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
DROP TRIGGER IF EXISTS tr1;
DROP FUNCTION IF EXISTS f1;
CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY);
CREATE PROCEDURE p1()
BEGIN
DECLARE ins_count INT DEFAULT 10;
WHILE ins_count > 0 DO
INSERT INTO t1 VALUES (NULL);
SET ins_count = ins_count - 1;
END WHILE;
DELETE FROM t1 WHERE id = 1;
DELETE FROM t1 WHERE id = 2;
DELETE FROM t2 WHERE id = 1;
DELETE FROM t2 WHERE id = 2;
END//
CREATE PROCEDURE p2()
BEGIN
INSERT INTO t1 VALUES (NULL);
DELETE FROM t1 WHERE id = f1(3);
DELETE FROM t1 WHERE id = f1(4);
DELETE FROM t2 WHERE id = 3;
DELETE FROM t2 WHERE id = 4;
END//
CREATE TRIGGER tr1 BEFORE DELETE
ON t1 FOR EACH ROW
BEGIN
INSERT INTO t2 VALUES (NULL);
END//
CREATE FUNCTION f1 (i int) RETURNS int
BEGIN
INSERT INTO t2 VALUES (NULL);
RETURN i;
END//
CALL p1();
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Intvar # # INSERT_ID=1
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=2
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=3
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=4
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=5
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=6
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=7
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=8
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=9
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Intvar # # INSERT_ID=10
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Query # # use `test`; DELETE FROM t1 WHERE id = 1
master-bin.000001 # Query # # use `test`; DELETE FROM t1 WHERE id = 2
master-bin.000001 # Query # # use `test`; DELETE FROM t2 WHERE id = 1
master-bin.000001 # Query # # use `test`; DELETE FROM t2 WHERE id = 2
# Result on master
SELECT * FROM t1;
id
3
4
5
6
7
8
9
10
SELECT * FROM t2;
id
# Result on slave
SELECT * FROM t1;
id
3
4
5
6
7
8
9
10
SELECT * FROM t2;
id
DROP TRIGGER tr1;
CALL p2();
show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Intvar # # INSERT_ID=11
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (NULL)
master-bin.000001 # Query # # use `test`; DELETE FROM t1 WHERE id = f1(3)
master-bin.000001 # Query # # use `test`; DELETE FROM t1 WHERE id = f1(4)
master-bin.000001 # Query # # use `test`; DELETE FROM t2 WHERE id = 3
master-bin.000001 # Query # # use `test`; DELETE FROM t2 WHERE id = 4
# Result on master
SELECT * FROM t1;
id
5
6
7
8
9
10
11
SELECT * FROM t2;
id
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Result on slave
SELECT * FROM t1;
id
5
6
7
8
9
10
11
SELECT * FROM t2;
id
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DROP TABLE IF EXISTS t1, t2;
DROP PROCEDURE IF EXISTS p1;
DROP PROCEDURE IF EXISTS p2;
DROP FUNCTION IF EXISTS f1;
DROP TRIGGER IF EXISTS tr1;
Warnings:
Note 1360 Trigger does not exist