List:Commits« Previous MessageNext Message »
From:Luís Soares Date:May 28 2009 4:17pm
Subject:Re: bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2912)
Bug#43929
View as plain text  
Hi Alfranio,

  Good work. Thanks for the nice online discussion about this.
  I have posted some comments inline.

On Wed, 2009-05-27 at 09:37 +0000, Alfranio Correia wrote:
> #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-27
>       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 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
> 
>     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-27 09:37:34 +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-27 09:37:34 +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-27 09:37:34 +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-27 09:37:34
> +0000
> @@ -0,0 +1,133 @@
> +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;
>
> +########################################################################################
> +#                                     SINGLE STATEMENT
>
> +########################################################################################
> +BEGIN;
> +Got one of the listed errors
> +Got one of the listed errors
> +source include/diff_master_slave.inc;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +2
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +2
> +TRUNCATE TABLE t1;
> +BEGIN;
> +Got one of the listed errors
> +Got one of the listed errors
> +Got one of the listed errors
> +BEGIN;
> +INSERT INTO t1(a, data) VALUES (17, 's');
> +INSERT INTO t1(a, data) VALUES (18, 's');
> +COMMIT;
> +source include/diff_master_slave.inc;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +7203
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +7203
>
> +########################################################################################
> +#                                     BEGIN - COMMIT
>
> +########################################################################################
> +TRUNCATE TABLE t1;
> +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;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +7201
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +7201
>
> +########################################################################################
> +#                                      BEGIN - ROLLBACK
>
> +########################################################################################
> +TRUNCATE TABLE t1;
> +BEGIN;
> +Got one of the listed errors
> +Got one of the listed errors
> +Got one of the listed errors
> +ROLLBACK;
> +source include/diff_master_slave.inc;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +NULL
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +NULL
>
> +########################################################################################
> +#                                         PROCEDURE 
>
> +########################################################################################
> +TRUNCATE TABLE t1;
> +CREATE PROCEDURE p1(pd VARCHAR(2500))
> +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;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +NULL
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +NULL
>
> +########################################################################################
> +#                                           XID
>
> +########################################################################################
> +TRUNCATE TABLE t1;
> +BEGIN;
> +Got one of the listed errors
> +Got one of the listed errors
> +Got one of the listed errors
> +ROLLBACK TO sv;
> +COMMIT;
> +source include/diff_master_slave.inc;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +7200
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +7200
>
> +########################################################################################
> +#                                        NON-TRANS TABLE
>
> +########################################################################################
> +TRUNCATE TABLE t1;
> +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;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +SUM(LENGTH(data))
> +4801
> +BEGIN;
> +Got one of the listed errors
>
> +########################################################################################
> +#                                        CLEAN
>
> +########################################################################################
> 
> === 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-27 09:37:34
> +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-27 09:37:34
> +0000
> @@ -0,0 +1,272 @@
>
> +########################################################################################
> +#    This test verifies if the binlog is not corrupted when the cache buffer is not
> +#    big enough to accomodate the updates.
>
> +########################################################################################


Please, add a brief summary for each of the test cases below.

I would also suggest that some extra tests with: 1. temporary tables and
2. autocommit with multiple tables (some non-transactional).

>
> +########################################################################################
> +#                                Configuring the environment
>
> +########################################################################################
> +-- source include/have_innodb.inc
> +--source include/master-slave.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;
> +
> +--source suite/rpl/include/bug43929_binlog.sql
> +
> +--echo
> ########################################################################################
> +--echo #                                     SINGLE STATEMENT
> +--echo
> ########################################################################################
> +
> +connection master;
> +
> +BEGIN;
> +--disable_query_log
> +eval INSERT INTO t1 (a, data) VALUES (0,'a'); 
> +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE
> +eval INSERT INTO t1 (a, data) VALUES (1,
> +     CONCAT($data, $data, $data, $data, $data));
> +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE
> +eval INSERT INTO t1 (a, data) VALUES (2,
> +     CONCAT($data, $data, $data, $data, $data));
> +eval INSERT INTO t1 (a, data) VALUES (4,'a'); 
> +--disable_query_log
> +COMMIT;
> +
> +let $diff_statement= SELECT * FROM t1;
> +--source include/diff_master_slave.inc
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +connection slave;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +#--echo
> ########################################################################################
> +#--echo #                                     BEGIN - BEGIN
> +#--echo
> ########################################################################################
> +
> +connection master;
> +TRUNCATE TABLE t1;
> +
> +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');
> +--enable_query_log
> +
> +BEGIN;
> +INSERT INTO t1(a, data) VALUES (17, 's');
> +INSERT INTO t1(a, data) VALUES (18, 's');
> +COMMIT;
> +
> +let $diff_statement= SELECT * FROM t1;
> +--source include/diff_master_slave.inc
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +connection slave;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +--echo
> ########################################################################################
> +--echo #                                     BEGIN - COMMIT
> +--echo
> ########################################################################################
> +
> +connection master;
> +TRUNCATE TABLE t1;
> +
> +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');
> +--enable_query_log
> +COMMIT;
> +
> +let $diff_statement= SELECT * FROM t1;
> +--source include/diff_master_slave.inc
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +connection slave;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +--echo
> ########################################################################################
> +--echo #                                      BEGIN - ROLLBACK
> +--echo
> ########################################################################################
> +
> +connection master;
> +TRUNCATE TABLE t1;
> +
> +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');
> +--enable_query_log
> +ROLLBACK;
> +
> +let $diff_statement= SELECT * FROM t1;
> +--source include/diff_master_slave.inc
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +connection slave;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +--echo
> ########################################################################################
> +--echo #                                         PROCEDURE 
> +--echo
> ########################################################################################
> +
> +connection master;
> +TRUNCATE TABLE t1;
> +
> +DELIMITER //;
> +
> +CREATE PROCEDURE p1(pd VARCHAR(2500))
> +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
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +connection slave;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +--echo
> ########################################################################################
> +--echo #                                           XID
> +--echo
> ########################################################################################
> +
> +connection master;
> +TRUNCATE TABLE t1;
> +
> +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);
> +SAVEPOINT sv;
> +--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');
> +--enable_query_log
> +ROLLBACK TO sv;
> +COMMIT;
> +
> +let $diff_statement= SELECT * FROM t1;
> +--source include/diff_master_slave.inc
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +connection slave;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +--echo
> ########################################################################################
> +--echo #                                        NON-TRANS TABLE
> +--echo
> ########################################################################################
> +
> +connection master;
> +TRUNCATE TABLE t1;
> +
> +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');
> +--enable_query_log
> +COMMIT;
> +
> +connection master;
> +SELECT SUM(LENGTH(data)) FROM t1;
> +
> +BEGIN;
> +--disable_query_log
> +--eval INSERT INTO t1 (a, data) VALUES (12, $data);
> +--eval INSERT INTO t1 (a, data) VALUES (13, $data);
> +--eval INSERT INTO t2 (a, data) VALUES (14, $data);
> +--error ER_TRANS_CACHE_FULL, ER_BINLOG_LOGGING_IMPOSSIBLE
> +--eval INSERT INTO t1 (a, data) VALUES (15, $data);
> +COMMIT;
> +
> +connection slave;
> +--source include/wait_for_slave_sql_to_stop.inc
> +
> +--echo
> ########################################################################################
> +--echo #                                        CLEAN
> +--echo
> ########################################################################################
> +
> +connection master;
> +DROP TABLE t1;
> +DROP TABLE t2;
> +DROP PROCEDURE p1;
> +connection slave;
> +DROP TABLE t1;
> +DROP TABLE t2;
> +DROP PROCEDURE p1;
> 
> === modified file 'sql/log.cc'
> --- a/sql/log.cc	2009-04-09 15:25:25 +0000
> +++ b/sql/log.cc	2009-05-27 09:37:34 +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,8 +1568,9 @@ 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 ||
> +  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))
>    {

Check that OPTION_KEEP_LOG does not have side effects on this patch.

>      /*
> @@ -1561,8 +1585,7 @@ 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

This comment is a bit ambiguous now. Please make it more clear.

> @@ -1570,12 +1593,57 @@ static int binlog_rollback(handlerton *h
>        log.
>       */
>      error= binlog_end_trans(thd, trx_data, 0, all);
> +    if (thd->transaction.all.modified_non_trans_table && 
> +        !trx_data->has_incident() &&
> mysql_bin_log.check_write_error(thd))
> +    {

>From handler.cc:

" In autocommit mode thd->transaction.all is empty.
  Instead, data of thd->transaction.stmt is
  used to commit/rollback the normal transaction. "

Probably you are missing another condition in the if above:

if (( thd->transaction.all.modified_non_trans_table ||
      thd->transaction.stmt.modified_non_trans_table ) && ...


> +      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);
> +    }
>    }
>    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 +3919,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 +3994,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 +4046,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;
>        }
>        /*
> @@ -4071,10 +4140,10 @@ 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_ERROR_ON_WRITE, MYF(MY_WME), name, errno);
> +      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-27 09:37:34 +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-27 09:37:34 +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-27 09:37:34 +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-27 09:37:34 +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
>        }
> 

Regards,
Luís


Thread
bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2912)Bug#43929Alfranio Correia27 May
  • Re: bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2912)Bug#43929Luís Soares28 May
    • Re: bzr commit into mysql-5.1-bugteam branch (alfranio.correia:2912)Bug#43929Alfranio Correia29 May