Bug #48608 | mysql replication slave trigger auto_increment columns | ||
---|---|---|---|
Submitted: | 6 Nov 2009 19:20 | Modified: | 24 Feb 2010 20:58 |
Reporter: | Ben R | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: Replication | Severity: | S3 (Non-critical) |
Version: | 5.1.40, 5.0, 5.1, next-mr bzr | OS: | Linux |
Assigned to: | Alfranio Tavares Correia Junior | CPU Architecture: | Any |
Tags: | auto_increment replication |
[6 Nov 2009 19:20]
Ben R
[6 Nov 2009 19:40]
Ben R
I should have added as clarification: the reason this all occurs is because in the bin logs, when the server is "changed", the statement is used in the bin logs SET @@session.auto_increment_increment=5, @@session.auto_increment_offset=2/*!*/; This also causes additional weirdness when you have master-master replication where one of the masters also has a slave. Because the auto_increment_increment only changed when the server_id changes in the binlogs, the auto_inc ids of table2 in the example above have values of both master's auto_increment_offset values.
[7 Nov 2009 2:01]
Ben R
I forgot to include the trigger. You probably could have just guessed this, but here is an example: DROP TRIGGER /*!50114 IF EXISTS */ table1_insert; DELIMITER // CREATE TRIGGER table1_insert AFTER INSERT ON table1 FOR EACH ROW BEGIN INSERT IGNORE INTO table2 SET some_value = 2; END // DELIMITER ;
[19 Nov 2009 11:03]
Sveta Smirnova
Thank you for the report. Verified as described. Probably documentation issue really. Test case for MTR: --source include/master-slave.inc CREATE TABLE `table1` ( `some_value` int(11) NOT NULL DEFAULT '0' ) DEFAULT CHARSET=latin1; set auto_increment_increment = 5; set auto_increment_offset = 2; connection slave; sleep 1; CREATE TABLE `table2` ( `table2_id` int(11) unsigned NOT NULL AUTO_INCREMENT, `some_value` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`table2_id`) ) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 ; DELIMITER //; CREATE TRIGGER table1_insert AFTER INSERT ON table1 FOR EACH ROW BEGIN INSERT IGNORE INTO table2 SET some_value = 2; END // DELIMITER ;// connection master; insert into table1 (some_value) VALUES (1); insert into table1 (some_value) VALUES (1); insert into table1 (some_value) VALUES (1); insert into table1 (some_value) VALUES (1); connection slave; sleep 1; select * from table2; Workaround: reset auto_increment_increment and auto_increment_offset in TRIGGER
[21 Dec 2009 9:40]
Alfranio Tavares Correia Junior
Zhenxing, Alfranio and Sven discussed this on IRC. And propose the following fix: (1) Create a new event type that holds (1) the table name; (2) the insert_id for that table. (2) Create a new variable, say INSERT_ID_LIST, that holds a list of table names and insert_id's. Example: INSERT_ID_LIST=t1:47,t2:11. This should be cleared after each top-level statement. This should fix most problems with autoinc when binlog_format=STATEMENT. (3) Mark all statements that insert into autoinc columns as unsafe. Autoinc will never work for sure when binlog_format=STATEMENT, because the optimizer may re-order operations so that two rows in the same table are inserted in a different order on master and slave. See thread "To discuss on replication call 090916: BUG#45677 and INSERT_ID".
[21 Dec 2009 9:48]
Alfranio Tavares Correia Junior
See also BUG##45677.
[22 Feb 2010 11:35]
Andrei Elkin
The bug issue is actually in many ways a dup of Bug #45677. The essence is in that stored routines can not have even just one auto-inc field w/o sacrificing replication consistency. Possibility to refine Bug #45677 fixes to provide unlimited support for auto-inc is viewed to me as rather theoretic.
[24 Feb 2010 20:27]
Alfranio Tavares Correia Junior
Please, ignore the comment "[21 Dec 2009 10:40] Alfranio Correia". After analyzing the problems related to auto_increment columns and discussing with the replication team, we realized that the solution proposed in "[21 Dec 2009 10:40] Alfranio Correia" does not fix all problems and may be infeasible to implement. See also bugs: BUG#45677 and BUG#50440.
[24 Feb 2010 20:55]
Alfranio Tavares Correia Junior
This is not a bug as the slave is just trying to mimic the master's behavior. Unfortunately, this is a limitation of the server. If we had created the same table (i.e. `table2`) on the master, the result would be the same: select * from table2; table2_id some_value 2 2 7 2 12 2 17 2 "This happens because is not possible to confine the effects of these two variables to a single table, and thus they do not take the place of the sequences offered by some other database management systems; these variables control the behavior of all AUTO_INCREMENT columns in all tables on the MySQL server. If the global value of either variable is set, its effects persist until the global value is changed or overridden by setting the session value, or until mysqld is restarted. If the local value is set, the new value affects AUTO_INCREMENT columns for all tables into which new rows are inserted by the current user for the duration of the session, unless the values are changed during that session." See http://tinyurl.com/y9vquwp for further information. So, in order to get the following result select * from table2; table2_id some_value 1 2 2 2 3 2 4 2 we need to change the trigger as follows DELIMITER //; CREATE TRIGGER table1_insert AFTER INSERT ON table1 FOR EACH ROW BEGIN set auto_increment_increment = 1; set auto_increment_offset = 1; INSERT IGNORE INTO table2 SET some_value = 2; END // DELIMITER ;//
[2 Nov 2010 4:06]
Roel Van de Paar
See bug #50440 | bug #53079 | bug #45677 | bug #42415