From: Alfranio Correia Date: May 29 2009 10:30am Subject: bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2912) Bug#43929 List-Archive: http://lists.mysql.com/commits/75226 X-Bug: 43929 Message-Id: <0KKE00I8NIIIQAE0@fe-emea-10.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_wt6BLvWXibsfaewdajqylQ)" --Boundary_(ID_wt6BLvWXibsfaewdajqylQ) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-43929/mysql-5.1-bugteam/ based on revid:bjorn.munch@stripped 2912 Alfranio Correia 2009-05-29 BUG#43929 binlog corruption when max_binlog_cache_size is exceeded Large transactions and statements may corrupt the binary log if the size of the cache, which is set by the max_binlog_cache_size, is not enough to store the the changes. In a nutshell, to fix the bug, we save the position of the next character in the cache before starting processing a statement. If there is a problem, we simply restore the position thus removing any effect of the statement from the cache. Unfortunately, to avoid corrupting the binary log, we may end up loosing changes on non-transactional tables if they do not fit in the cache. In such cases, we store an Incident_log_event in order to stop the slave and alert users that some changes were not logged. Precisely, for every non-transactional changes that cannot fit into the cache, we do the following: a) its respective statement gives an error b) the statement is *not* logged c) an incident event is logged For transactional changes that cannot fit into the cache, we do the following: a) its respective statement gives an error b) the statement is *not* logged To work properly, this patch requires that callers to MYSQL_BIN_LOG::write and THD::binlog_query handle any error returned and take the appropriate actions such as undoing the effects of a statement. We already changed some calls from the sql_insert.cc, sql_update.cc and sql_insert.cc modules but the remaining calls spread all over the code should be handled in BUG#37148. added: mysql-test/suite/rpl/include/bug43929_binlog.sql mysql-test/suite/rpl/r/rpl_binlog_max_cache_size.result mysql-test/suite/rpl/t/rpl_binlog_max_cache_size-master.opt mysql-test/suite/rpl/t/rpl_binlog_max_cache_size.test modified: mysql-test/include/commit.inc mysql-test/r/commit_1innodb.result sql/log.cc sql/log.h sql/sql_delete.cc sql/sql_insert.cc sql/sql_update.cc === modified file 'mysql-test/include/commit.inc' --- a/mysql-test/include/commit.inc 2009-01-23 12:22:05 +0000 +++ b/mysql-test/include/commit.inc 2009-05-29 10:20:18 +0000 @@ -669,13 +669,9 @@ call p_verify_status_increment(1, 0, 1, insert t1 set a=3; call p_verify_status_increment(2, 2, 2, 2); savepoint a; -call p_verify_status_increment(0, 0, 0, 0); +call p_verify_status_increment(1, 0, 0, 0); insert t1 set a=4; ---echo # Binlog does not register itself this time for other than the 1st ---echo # statement of the transaction with MIXED/STATEMENT binlog_format. ---echo # It needs registering with the ROW format. Therefore 1,0,2,2 are ---echo # the correct arguments to this test after bug#40221 fixed. -call p_verify_status_increment(1, 0, 2, 2); +call p_verify_status_increment(2, 2, 2, 2); release savepoint a; rollback; call p_verify_status_increment(0, 0, 0, 0); === modified file 'mysql-test/r/commit_1innodb.result' --- a/mysql-test/r/commit_1innodb.result 2009-02-10 14:44:58 +0000 +++ b/mysql-test/r/commit_1innodb.result 2009-05-29 10:20:18 +0000 @@ -766,15 +766,11 @@ call p_verify_status_increment(2, 2, 2, SUCCESS savepoint a; -call p_verify_status_increment(0, 0, 0, 0); +call p_verify_status_increment(1, 0, 0, 0); SUCCESS insert t1 set a=4; -# Binlog does not register itself this time for other than the 1st -# statement of the transaction with MIXED/STATEMENT binlog_format. -# It needs registering with the ROW format. Therefore 1,0,2,2 are -# the correct arguments to this test after bug#40221 fixed. -call p_verify_status_increment(1, 0, 2, 2); +call p_verify_status_increment(2, 2, 2, 2); SUCCESS release savepoint a; === added file 'mysql-test/suite/rpl/include/bug43929_binlog.sql' --- a/mysql-test/suite/rpl/include/bug43929_binlog.sql 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/include/bug43929_binlog.sql 2009-05-29 10:20:18 +0000 @@ -0,0 +1,36 @@ +let $data='vb +alxxMCC5o X3dAkvHXY,WhFV72Z6;oNHpL,WfTAOYKMdb8OQ tUfYXjlNcois8V7hcnk5;.ixojWOcBpMGOVQl9,p3 v313eQ3j6mbGH7nh3sQeJn, +G aEbB8 :YorJ1 wPzDerR8kLazeliXwxedpxhNUel0XpBO.KLdjNW MGlkaNSbtQVpfcmR wZPeyLWK0avXphFRd:5c4dCEMC XHsZvEZy Q1CrNIGTaJuKIkH5UEaDuacHzICkRugIn nW1Z MHYV7w d ZYA:U;V4Kku99ioob4TQHlLlanD RH vUq64phzC77pPIhf3PWxlB dLhimAG ;l0UMCqxV2alAHV iW,uIfp2,UH2 7Kf +dJHeh4VmzxmAP6lG6ih2uIwfl;KwcLN qGrF70W , :QxfiB X7 dhEMEP: r3RllCaS.CTCCBaMQa;87vvEZnO6NmLsoEeoQx:zG6UTKvHRSyWcYC7bcWDF,jngS7QNZQwyoY H7ZC0ocebLf NpTy42NJ cupL LYQ7Xg2X16h2T +csX,sqT B hRDsocDBBuu9j Iz9k EL1VuamulUc3zsFHI.dKWQRyCPTE0NEiy4eMNhBT4 L1Klqey YmWYuXZkrFUV89c:AONXIg + DsvgkPgNwZOTi; 9DGec F2XHLWH1yY R1Cjh 5PmE60jAl3B4SOz.coG:Oy.G boG 4;kZRTpIBda3eG3S6 +s2; Y.a vEV:MZKvOf6 +U3jkTX49wafxd;i:gJ +sxTpvLa2B2jj 4cBG Bazi5 XpKqfTcBW0iUhKDlD6KamzWUk +R9i +n,STLTyG6DP:WH1fmw5:N wmQU3kpSJsGeXwxJ .BnmaMdcfqqinSpryqgTBvQ ,B:feTao.xkF.:l tY pW3u;D CbU +8ahKp4rteHuaX +, zXZ4kT 9DX;8Rwwi6JNaDWkSO6JHtjczuZat.NxW,UM0w2s5gCOgbx:jlfEeq4XDe1xsFHORNa 0RTT ftMPj7eqP OkqUteCtOyfweMZ;LdvYwGFjM7xOfa9jSQv6Ypmhd;MIZ.rBb,p7Ce3aPDra8eoKy6YxLsqxPIzAO pZPVTrmmj7Jyc.QVmF57gdRMv3X8kXcvTz TArOZ wZr4acAu8eJjr +7Z;.Sy3p9nGivSprQjVR:X0,Af4iYk,WAoXRyT tu09b6c:v.Ci 7EMjstiR7,f L653d hfswxvY;IB.gWXEVFn3EhhxoYCcL0fftXcf Ec3ZW9 A2hYMa;F9GWeCvshNZc2:Bwa5VzwaarfVpf +HSA4iREIbgg a,;61. + +5 rnGNC CsaoRevNeDjhN80 wB.bS7oL ,ioctAQWi9gQS 6pV .pgLtnbPA:gEz:Mq:DkAtpulNoziTWitVAoMu;zwrKibXoQEHU0ji4CJ4GSUuzZ,yrmPe1Tx 2n8mJ15Aa7f +abtu +rgaf +yWY2m8pM2Ps gmiMdJXiYQkU0Girlk;OhB;mdClF.dWhvl:NhkIUoWEO0b6b13pxB3XXa3V Kr3l.edsfoX950p:cmPPlNrOiAl.Oat934PC +dM hBgUUk:RCgi.uGTu.tG0Umia7 9.2u1L.yE6ToYn7sB;aF9mups.v3XJYJh3gkaOojNU7:;Q2OpiIrnee1VRn 6q DY9nFwe9zjZ8ciJ oUQLaEooVFhuner;ZFRO2 +lHu:w0Lu +dajd2lZ3FBw +j +X +aaUARW xmaccUvRc3b6V5nrVHnOTQFpWYCoqvat1dtNl8aY +KEa6YzWL8,Le53mjfK +FQp8r4RFOj7:xVSWr1GQbKKXiKd4C7tblGaSy8VU9w7Wkr6 SVKaJn6Nd1hWymraIH0K13bb3 K,0ersTE.hX2 +Z xS1lC98j,g9V:4kU1E ZR;Fhpa2Jfr3MY:Vsz +T1c2aV8q5b4;NCEnu5;M5S.i9 tI1EIK;Lban Z +06nyfms94A7ukJ2h8utxZSa6PX52k81L1VR 6Z TXlVfLa;18bSy;LhHpOY,B3Z0 e5N0WXgVqh,1AV25CHLJ;yFtz;Pr011 Mqhya.phYDvzzJYrPY6;Znji +cYC2kIv;FqS otKpKQ:hOThDkwU2AnGZs848aF6kH1rgyRJWGcihB +kXhjBfb0zM2bL,Jmpb3K3GEIMNzc35V THnO495KjefyL.Lvfmt nk saDs qo;hHpOW,;12 +ZTXRWxxt +qKIfVus3D:mvPd8wq4Vw0cItYLeta2E6MP78kdJlBPxGbtSRyPtG6MD4GNYIroTNohSWwiy5v0iXeFzeaDkdb:qfK9eICd LD GStfa +mOe,Uhs ul;Ziev3 mleNCPku8aDKovqPd,OX:JN 3,Sb 9WwS:gprHC n6E1'; === added file 'mysql-test/suite/rpl/r/rpl_binlog_max_cache_size.result' --- a/mysql-test/suite/rpl/r/rpl_binlog_max_cache_size.result 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/r/rpl_binlog_max_cache_size.result 2009-05-29 10:20:18 +0000 @@ -0,0 +1,137 @@ +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; +CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=Innodb; +CREATE TABLE t2(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MyIsam; +CREATE TABLE t3(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=Innodb; +######################################################################################## +# 1 - SINGLE STATEMENT +######################################################################################## +*** Single statment on transactional table *** +Got one of the listed errors +*** Single statment on non-transactional table *** +*** After WL#2687 the difference between STATEMENT/MIXED and ROW will not exist. *** +Got one of the listed errors +*** Single statment on both transactional and non-transactional tables. *** +*** After WL#2687 we will be able to change the order of the tables. *** +Got one of the listed errors +RESET MASTER; +STOP SLAVE; +RESET SLAVE; +START SLAVE; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +BEGIN; +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +BEGIN; +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +BEGIN; +Got one of the listed errors +Got one of the listed errors +source include/diff_master_slave.inc; +######################################################################################## +# 3 - BEGIN - COMMIT +######################################################################################## +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +BEGIN; +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +COMMIT; +source include/diff_master_slave.inc; +######################################################################################## +# 4 - BEGIN - ROLLBACK +######################################################################################## +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +BEGIN; +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +source include/diff_master_slave.inc; +######################################################################################## +# 5 - PROCEDURE +######################################################################################## +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +CREATE PROCEDURE p1(pd VARCHAR(30000)) +BEGIN +INSERT INTO t1 (a, data) VALUES (1, pd); +INSERT INTO t1 (a, data) VALUES (2, pd); +INSERT INTO t1 (a, data) VALUES (3, pd); +INSERT INTO t1 (a, data) VALUES (4, pd); +INSERT INTO t1 (a, data) VALUES (5, 's'); +END// +TRUNCATE TABLE t1; +TRUNCATE TABLE t1; +BEGIN; +Got one of the listed errors +COMMIT; +TRUNCATE TABLE t1; +BEGIN; +Got one of the listed errors +ROLLBACK; +source include/diff_master_slave.inc; +######################################################################################## +# 6 - XID +######################################################################################## +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +BEGIN; +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +ROLLBACK TO sv; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +COMMIT; +source include/diff_master_slave.inc; +######################################################################################## +# 7 - NON-TRANS TABLE +######################################################################################## +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +BEGIN; +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +Got one of the listed errors +COMMIT; +BEGIN; +Got one of the listed errors +COMMIT; +######################################################################################## +# CLEAN +######################################################################################## +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE IF EXISTS t4; +DROP TABLE IF EXISTS t5; +DROP TABLE IF EXISTS t6; +DROP PROCEDURE p1; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE IF EXISTS t4; +DROP TABLE IF EXISTS t5; +DROP TABLE IF EXISTS t6; +DROP PROCEDURE p1; === added file 'mysql-test/suite/rpl/t/rpl_binlog_max_cache_size-master.opt' --- a/mysql-test/suite/rpl/t/rpl_binlog_max_cache_size-master.opt 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_binlog_max_cache_size-master.opt 2009-05-29 10:20:18 +0000 @@ -0,0 +1 @@ +--binlog_cache_size=4096 --max_binlog_cache_size=8192 === added file 'mysql-test/suite/rpl/t/rpl_binlog_max_cache_size.test' --- a/mysql-test/suite/rpl/t/rpl_binlog_max_cache_size.test 1970-01-01 00:00:00 +0000 +++ b/mysql-test/suite/rpl/t/rpl_binlog_max_cache_size.test 2009-05-29 10:20:18 +0000 @@ -0,0 +1,404 @@ +######################################################################################## +# This test verifies if the binlog is not corrupted when the cache buffer is not +# big enough to accommodate the updates. +# +# 1 - Single Statements: +# 1.1 - Single statement on transactional table. +# 1.2 - Single statement on non-transactional table. +# 1.3 - Single statement on both transactional and non-transactional tables. +# In both 1.2 and 1.3, an incident event is logged to notify the user that the +# master and slave are diverging. +# +# 2 - Transactions ended by an implicit commit. +# +# 3 - Transactions ended by a COMMIT. +# +# 4 - Transactions ended by a ROLLBACK. +# +# 5 - Transactions with a failing statement that updates a non-transactional +# table. In this case, a failure means that the statement does not get into +# the cache and an incident event is logged to notify the user that the master +# and slave are diverging. +# +######################################################################################## + +######################################################################################## +# Configuring the environment +######################################################################################## +--source include/have_innodb.inc +--source include/master-slave.inc +--source include/not_embedded.inc +--source include/not_windows.inc + +CREATE TABLE t1(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=Innodb; +CREATE TABLE t2(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=MyIsam; +CREATE TABLE t3(a INT PRIMARY KEY, data VARCHAR(30000)) ENGINE=Innodb; + +--source suite/rpl/include/bug43929_binlog.sql + +--echo ######################################################################################## +--echo # 1 - SINGLE STATEMENT +--echo ######################################################################################## + +connection master; + +--echo *** Single statment on transactional table *** +--disable_query_log +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +eval INSERT INTO t1 (a, data) VALUES (1, + CONCAT($data, $data, $data, $data, $data)); +--enable_query_log + +--echo *** Single statment on non-transactional table *** +--echo *** After WL#2687 the difference between STATEMENT/MIXED and ROW will not exist. *** +--disable_query_log +--disable_warnings +if (`SELECT @@binlog_format = 'STATEMENT' || @@binlog_format = 'MIXED'`) +{ + eval INSERT INTO t2 (a, data) VALUES (2, + CONCAT($data, $data, $data, $data, $data, $data)); + --echo Got one of the listed errors +} +if (`SELECT @@binlog_format = 'ROW'`) +{ + --error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE + eval INSERT INTO t2 (a, data) VALUES (2, + CONCAT($data, $data, $data, $data, $data, $data)); + + RESET MASTER; + connection slave; + --source include/wait_for_slave_sql_to_stop.inc + STOP SLAVE; + --source include/wait_for_slave_to_stop.inc + RESET SLAVE; + START SLAVE; + --source include/wait_for_slave_to_start.inc +} +--enable_warnings +--enable_query_log + +connection master; + +--disable_query_log +eval INSERT INTO t1 (a, data) VALUES (3, $data); +eval INSERT INTO t1 (a, data) VALUES (4, $data); +eval INSERT INTO t1 (a, data) VALUES (5, $data); +eval INSERT INTO t2 (a, data) VALUES (3, $data); +eval INSERT INTO t2 (a, data) VALUES (4, $data); +eval INSERT INTO t2 (a, data) VALUES (5, $data); +--enable_query_log + +--echo *** Single statment on both transactional and non-transactional tables. *** +--echo *** After WL#2687 we will be able to change the order of the tables. *** +--disable_query_log +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +eval UPDATE t2, t1 SET t2.data = CONCAT($data, $data, $data, $data), + t1.data = CONCAT($data, $data, $data, $data); +--enable_query_log + +RESET MASTER; +connection slave; +--source include/wait_for_slave_sql_to_stop.inc +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc +RESET SLAVE; +START SLAVE; +--source include/wait_for_slave_to_start.inc + +#--echo ######################################################################################## +#--echo # 2 - BEGIN - IMPLICIT COMMIT by DDL +#--echo ######################################################################################## + +connection master; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (1, $data); +--eval INSERT INTO t1 (a, data) VALUES (2, $data); +--eval INSERT INTO t1 (a, data) VALUES (3, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (4, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (5, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (6, $data); +--eval INSERT INTO t1 (a, data) VALUES (7, 's'); +--eval INSERT INTO t2 (a, data) VALUES (8, 's'); +--eval INSERT INTO t1 (a, data) VALUES (9, 's'); +--enable_query_log + +--disable_query_log +ALTER TABLE t3 ADD COLUMN d int; +--enable_query_log + +--disable_query_log +--eval INSERT INTO t2 (a, data) VALUES (10, $data); +--eval INSERT INTO t2 (a, data) VALUES (11, $data); +--eval INSERT INTO t2 (a, data) VALUES (12, $data); +--eval INSERT INTO t2 (a, data) VALUES (13, $data); +--enable_query_log + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (14, $data); +--eval INSERT INTO t1 (a, data) VALUES (15, $data); +--eval INSERT INTO t1 (a, data) VALUES (16, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (17, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (18, $data); +--eval INSERT INTO t1 (a, data) VALUES (19, 's'); +--eval INSERT INTO t2 (a, data) VALUES (20, 's'); +--eval INSERT INTO t1 (a, data) VALUES (21, 's'); +--enable_query_log + +if (`SELECT @@binlog_format = 'STATEMENT' || @@binlog_format = 'MIXED'`) +{ + --disable_query_log + CREATE TABLE t4 SELECT * FROM t1; + --enable_query_log + --echo Got one of the listed errors +} +if (`SELECT @@binlog_format = 'ROW'`) +{ + --disable_query_log + --error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE + CREATE TABLE t4 SELECT * FROM t1; + --enable_query_log +} + +--disable_query_log +--eval INSERT INTO t2 (a, data) VALUES (15, $data); +--enable_query_log + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (22, $data); +--eval INSERT INTO t1 (a, data) VALUES (23, $data); +--eval INSERT INTO t1 (a, data) VALUES (24, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (25, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (26, $data); +--eval INSERT INTO t1 (a, data) VALUES (27, 's'); +--eval INSERT INTO t2 (a, data) VALUES (28, 's'); +--eval INSERT INTO t1 (a, data) VALUES (29, 's'); +--enable_query_log + +--disable_query_log +CREATE TABLE t5 (a int); +--enable_query_log + +let $diff_statement= SELECT * FROM t1; +--source include/diff_master_slave.inc + +--echo ######################################################################################## +--echo # 3 - BEGIN - COMMIT +--echo ######################################################################################## + +connection master; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (1, $data); +--eval INSERT INTO t1 (a, data) VALUES (2, $data); +--eval INSERT INTO t1 (a, data) VALUES (3, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (4, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (5, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (6, $data); +--eval INSERT INTO t1 (a, data) VALUES (7, 's'); +--eval INSERT INTO t2 (a, data) VALUES (8, 's'); +--eval INSERT INTO t1 (a, data) VALUES (9, 's'); +--enable_query_log +COMMIT; + +let $diff_statement= SELECT * FROM t1; +--source include/diff_master_slave.inc + +--echo ######################################################################################## +--echo # 4 - BEGIN - ROLLBACK +--echo ######################################################################################## + +connection master; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (1, $data); +--eval INSERT INTO t1 (a, data) VALUES (2, $data); +--eval INSERT INTO t1 (a, data) VALUES (3, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (4, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (5, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (6, $data); +--eval INSERT INTO t1 (a, data) VALUES (7, 's'); +--eval INSERT INTO t2 (a, data) VALUES (8, 's'); +--eval INSERT INTO t1 (a, data) VALUES (9, 's'); +--enable_query_log +ROLLBACK; + +let $diff_statement= SELECT * FROM t1; +--source include/diff_master_slave.inc + +--echo ######################################################################################## +--echo # 5 - PROCEDURE +--echo ######################################################################################## + +connection master; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +DELIMITER //; + +CREATE PROCEDURE p1(pd VARCHAR(30000)) +BEGIN + INSERT INTO t1 (a, data) VALUES (1, pd); + INSERT INTO t1 (a, data) VALUES (2, pd); + INSERT INTO t1 (a, data) VALUES (3, pd); + INSERT INTO t1 (a, data) VALUES (4, pd); + INSERT INTO t1 (a, data) VALUES (5, 's'); +END// + +DELIMITER ;// + +TRUNCATE TABLE t1; + +--disable_query_log +eval CALL p1($data); +--enable_query_log + +TRUNCATE TABLE t1; + +BEGIN; +--disable_query_log +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +eval CALL p1($data); +--enable_query_log +COMMIT; + +TRUNCATE TABLE t1; + +BEGIN; +--disable_query_log +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +eval CALL p1($data); +--enable_query_log +ROLLBACK; + +let $diff_statement= SELECT * FROM t1; +--source include/diff_master_slave.inc + +--echo ######################################################################################## +--echo # 6 - XID +--echo ######################################################################################## + +connection master; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (1, $data); +--eval INSERT INTO t1 (a, data) VALUES (2, $data); +--eval INSERT INTO t1 (a, data) VALUES (3, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (4, $data); +SAVEPOINT sv; +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (5, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (6, $data); +--eval INSERT INTO t1 (a, data) VALUES (7, 's'); +--eval INSERT INTO t2 (a, data) VALUES (8, 's'); +--eval INSERT INTO t1 (a, data) VALUES (9, 's'); +--enable_query_log +ROLLBACK TO sv; +COMMIT; + +let $diff_statement= SELECT * FROM t1; +--source include/diff_master_slave.inc + +--echo ######################################################################################## +--echo # 7 - NON-TRANS TABLE +--echo ######################################################################################## + +connection master; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (1, $data); +--eval INSERT INTO t1 (a, data) VALUES (2, $data); +--eval INSERT INTO t2 (a, data) VALUES (3, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (4, $data); +--eval INSERT INTO t2 (a, data) VALUES (5, $data); +--eval INSERT INTO t2 (a, data) VALUES (6, $data); +--eval INSERT INTO t2 (a, data) VALUES (7, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (8, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (9, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (10, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval UPDATE t2 SET data= CONCAT($data, $data); +--eval INSERT INTO t1 (a, data) VALUES (11, 's'); +--eval INSERT INTO t1 (a, data) VALUES (12, 's'); +--eval INSERT INTO t2 (a, data) VALUES (13, 's'); +--eval INSERT INTO t1 (a, data) VALUES (14, 's'); +--enable_query_log +COMMIT; + +BEGIN; +--disable_query_log +--eval INSERT INTO t1 (a, data) VALUES (15, $data); +--eval INSERT INTO t1 (a, data) VALUES (16, $data); +--eval INSERT INTO t2 (a, data) VALUES (17, $data); +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE +--eval INSERT INTO t1 (a, data) VALUES (18, $data); +--enable_query_log +COMMIT; + +connection slave; +--source include/wait_for_slave_sql_to_stop.inc + +--echo ######################################################################################## +--echo # CLEAN +--echo ######################################################################################## + +--disable_warnings +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE IF EXISTS t4; +DROP TABLE IF EXISTS t5; +DROP TABLE IF EXISTS t6; +DROP PROCEDURE p1; +connection slave; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP TABLE IF EXISTS t4; +DROP TABLE IF EXISTS t5; +DROP TABLE IF EXISTS t6; +DROP PROCEDURE p1; +--enable_warnings === modified file 'sql/log.cc' --- a/sql/log.cc 2009-04-09 15:25:25 +0000 +++ b/sql/log.cc 2009-05-29 10:20:18 +0000 @@ -153,9 +153,10 @@ private: class binlog_trx_data { public: binlog_trx_data() - : at_least_one_stmt(0), m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF) + : at_least_one_stmt(0), incident(FALSE), m_pending(0), + before_stmt_pos(MY_OFF_T_UNDEF) { - trans_log.end_of_file= max_binlog_cache_size; + calculate_cache_size(); } ~binlog_trx_data() @@ -184,6 +185,7 @@ public: delete pending(); set_pending(0); reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0); + calculate_cache_size(); if (pos < before_stmt_pos) before_stmt_pos= MY_OFF_T_UNDEF; @@ -206,7 +208,8 @@ public: if (!empty()) truncate(0); before_stmt_pos= MY_OFF_T_UNDEF; - trans_log.end_of_file= max_binlog_cache_size; + incident= FALSE; + calculate_cache_size(); DBUG_ASSERT(empty()); } @@ -222,11 +225,29 @@ public: IO_CACHE trans_log; // The transaction cache + void set_incident(void) + { + incident= TRUE; + } + + bool has_incident(void) + { + return(incident); + } + + my_off_t calculate_cache_size(void) + { + my_off_t diff= (incident ? 0 : reserved_cache_size); + trans_log.end_of_file= (((max_binlog_cache_size - diff) < IO_SIZE) ? + IO_SIZE : (max_binlog_cache_size - diff)); + return trans_log.end_of_file; + } /** Boolean that is true if there is at least one statement in the transaction cache. */ bool at_least_one_stmt; + bool incident; private: /* @@ -240,6 +261,7 @@ public: Binlog position before the start of the current statement. */ my_off_t before_stmt_pos; + static const my_off_t reserved_cache_size= 512; }; handlerton *binlog_hton; @@ -1391,7 +1413,8 @@ binlog_end_trans(THD *thd, binlog_trx_da */ if (end_ev != NULL) { - thd->binlog_flush_pending_rows_event(TRUE); + if (thd->binlog_flush_pending_rows_event(TRUE)) + DBUG_RETURN(1); /* Doing a commit or a rollback including non-transactional tables, i.e., ending a transaction where we might write the transaction @@ -1545,9 +1568,11 @@ static int binlog_rollback(handlerton *h YESNO(all), YESNO(thd->transaction.all.modified_non_trans_table), YESNO(thd->transaction.stmt.modified_non_trans_table))); - if (all && thd->transaction.all.modified_non_trans_table || - !all && thd->transaction.stmt.modified_non_trans_table || - (thd->options & OPTION_KEEP_LOG)) + if ((all && thd->transaction.all.modified_non_trans_table) || + (!all && thd->transaction.stmt.modified_non_trans_table && + !mysql_bin_log.check_write_error(thd)) || + ((thd->options & OPTION_KEEP_LOG) && + !mysql_bin_log.check_write_error(thd))) { /* We write the transaction cache with a rollback last if we have @@ -1561,21 +1586,82 @@ static int binlog_rollback(handlerton *h qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) error= binlog_end_trans(thd, trx_data, &qev, all); } - else if (all && !thd->transaction.all.modified_non_trans_table || - !all && !thd->transaction.stmt.modified_non_trans_table) + else { /* - If we have modified only transactional tables, we can truncate - the transaction cache without writing anything to the binary - log. + We reach this point if either only transactional tables were modified or + the effect of a statement that did not get into the binlog needs to be + rolled back. In the later case, if the statement changed non-transactional + tables or had the OPTION_KEEP_LOG associated, we write an incident event + to the binlog in order to stop the slave and notify users that some + changes on the master did not get into the binlog and the slave will be + inconsistent. On the other hand, if the statement is transactional is + safe to roll it back. */ error= binlog_end_trans(thd, trx_data, 0, all); + if ((thd->transaction.all.modified_non_trans_table || + thd->transaction.stmt.modified_non_trans_table || + (thd->options & OPTION_KEEP_LOG)) && + !trx_data->has_incident() && mysql_bin_log.check_write_error(thd)) + { + /* + We need to allocate extra space to write the incident event. + */ + trx_data->set_incident(); + trx_data->calculate_cache_size(); + LEX_STRING const write_error_msg= + { C_STRING_WITH_LEN("error writing to the binary log") }; + Incident incident= INCIDENT_LOST_EVENTS; + Incident_log_event ev(thd, incident, write_error_msg); + mysql_bin_log.write(&ev); + /* + We need to reset the cache if not in a transaction as there will be no + call to commit or rollback a transaction in order to unset the incident + flag and the extra space allocated. + */ + if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + trx_data->reset(); + } } if (!all) trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback DBUG_RETURN(error); } +void MYSQL_BIN_LOG::set_write_error(THD *thd) +{ + DBUG_ENTER("set_write_error"); + + if (check_write_error(thd)) + DBUG_VOID_RETURN; + + my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(MY_WME), + "Error writing events"); + + DBUG_VOID_RETURN; +} + +bool MYSQL_BIN_LOG::check_write_error(THD *thd) +{ + DBUG_ENTER("check_write_error"); + + bool checked= FALSE; + + if (!thd->is_error()) + DBUG_RETURN(checked); + + switch (thd->main_da.sql_errno()) + { + case ER_TRANS_CACHE_FULL: + case ER_ERROR_ON_WRITE: + case ER_BINLOG_LOGGING_IMPOSSIBLE: + checked= TRUE; + break; + } + + DBUG_RETURN(checked); +} + /** @note How do we handle this (unlikely but legal) case: @@ -3851,6 +3937,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_row if (pending->write(file)) { pthread_mutex_unlock(&LOCK_log); + set_write_error(thd); DBUG_RETURN(1); } @@ -3925,7 +4012,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve */ bool const end_stmt= thd->prelocked_mode && thd->lex->requires_prelocking(); - thd->binlog_flush_pending_rows_event(end_stmt); + if (thd->binlog_flush_pending_rows_event(end_stmt)) + DBUG_RETURN(error); pthread_mutex_lock(&LOCK_log); @@ -3976,8 +4064,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu", event_info->get_cache_stmt(), (ulong) trans_log_pos)); - if (trans_log_pos == 0) - thd->binlog_start_trans_and_stmt(); + thd->binlog_start_trans_and_stmt(); file= trans_log; } /* @@ -4055,7 +4142,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve Write the SQL command */ - if (event_info->write(file)) + if (event_info->write(file) || + DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0)) goto err; if (file == &log_file) // we are writing to the real log (disk) @@ -4071,10 +4159,11 @@ err: if (error) { if (my_errno == EFBIG) - my_message(ER_TRANS_CACHE_FULL, ER(ER_TRANS_CACHE_FULL), MYF(0)); + my_message(ER_TRANS_CACHE_FULL, ER(ER_TRANS_CACHE_FULL), MYF(MY_WME)); else - my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno); - write_error=1; + my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(MY_WME), + "Error writing events"); + write_error= 1; } } === modified file 'sql/log.h' --- a/sql/log.h 2009-01-23 12:22:05 +0000 +++ b/sql/log.h 2009-05-29 10:20:18 +0000 @@ -359,6 +359,8 @@ public: bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event); int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync); + void set_write_error(THD *thd); + bool check_write_error(THD *thd); void start_union_events(THD *thd, query_id_t query_id_param); void stop_union_events(THD *thd); === modified file 'sql/sql_delete.cc' --- a/sql/sql_delete.cc 2009-05-15 13:25:29 +0000 +++ b/sql/sql_delete.cc 2009-05-29 10:20:18 +0000 @@ -404,7 +404,7 @@ cleanup: thd->query, thd->query_length, is_trans, FALSE, killed_status); - if (log_result && transactional_table) + if (log_result) { error=1; } === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2009-05-15 12:57:51 +0000 +++ b/sql/sql_insert.cc 2009-05-29 10:20:18 +0000 @@ -893,8 +893,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, transactional_table, FALSE, - (error>0) ? thd->killed : THD::NOT_KILLED) && - transactional_table) + (error>0) ? thd->killed : THD::NOT_KILLED)) { error=1; } === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2009-05-15 13:03:22 +0000 +++ b/sql/sql_update.cc 2009-05-29 10:20:18 +0000 @@ -799,8 +799,7 @@ int mysql_update(THD *thd, thd->clear_error(); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, - transactional_table, FALSE, killed_status) && - transactional_table) + transactional_table, FALSE, killed_status)) { error=1; // Rollback update } @@ -2079,8 +2078,7 @@ bool multi_update::send_eof() thd->clear_error(); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, - transactional_tables, FALSE, killed_status) && - trans_safe) + transactional_tables, FALSE, killed_status)) { local_error= 1; // Rollback update } --Boundary_(ID_wt6BLvWXibsfaewdajqylQ) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name*0="bzr/alfranio.correia@stripped"; name*1=018-aeamp1jyhwqx8tek.bundle Content-transfer-encoding: 7BIT Content-disposition: inline; filename*0="bzr/alfranio.correia@stripped"; filename*1=018-aeamp1jyhwqx8tek.bundle # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: alfranio.correia@stripped\ # aeamp1jyhwqx8tek # target_branch: file:///home/acorreia/workspace.sun/repository.mysql\ # /bzrwork/bug-43929/mysql-5.1-bugteam/ # testament_sha1: 8d386066caaef184847135c196bfa281a458b83d # timestamp: 2009-05-29 11:30:13 +0100 # base_revision_id: bjorn.munch@stripped\ # zitq9aysxy5zgf5r # # Begin bundle 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 --Boundary_(ID_wt6BLvWXibsfaewdajqylQ)--