List:Commits« Previous MessageNext Message »
From:Rafal Somla Date:November 5 2007 6:55pm
Subject:Re: bk commit into 5.2 tree (cbell:1.2612)
View as plain text  
Hi Chuck,

I still think that the blocking of the commits by the commit blocker is not 
tested properly. Let's look at what happens in the first test:

 > +#   con1     con2     con3     con4     con5
 > +#  (setup)    |        |        |        |
 > +#     |       |        |        |        |
 > +#     |     BEGIN      |        |        |
 > +#     |    UPDATE t1   |        |        |
 > +#     |       |      BEGIN      |        |
 > +#     |       |     INSERT t2   |        |
 > +#     |       |     INSERT t2   |        |
 > +#     |       |        |        |  lock("commit_blocker_step_1");
 > +#   BACKUP    |        |        |        |
 > +#     |       |        |        |  <wait for locks>

The BACKUP command will stop inside block_commits() *before* the call to 
lock_global_read_lock(), that is, before blocking commits is activated - it 
happens in step 3 where make_global_read_lock_block_commit() is called. At the 
place where the "commit_blocker_step_1" breakpoint is placed not only commits 
are not blocked but the global write lock is not yet activated.

 > +#     |       |      COMMIT     |        |
 > +#     |       |        |        |  <wait for locks>

Commit will stop at the breakpoint inside end_trans() - not because it is 
blocked by the commit blocker.

 > +#     |       |        |        |  lock("backup_commit_blocker");

After this end_trans() will finish and COMMIT will stop after return from that 
function (inside the big switch).

BACKUP will complete uninterrupted. Chances are that it will not even wait for 
the COMMIT because end_trans() will exit before block_commits() calls 
make_global_read_lock_block_commit() which is the function supposed to wait for 
on-going commits to finish.

 > +#     |       |        |        |  <wait for locks>
 > +#     |       |        |      BEGIN      |
 > +#     |       |        |        |  <wait for locks>
 > +#     |       |        |        |  <release locks>
 > +#     |    DELETE t1   |        |        |
 > +#     |     COMMIT     |        |        |
 > +#     |       |      <...>      |        |
 > +#     |       |        |     UPDATE t3   |
 > +#     |       |        |     COMMIT      |
 > +#   <...>     |        |        |        |
 > +# (results)   |        |        |        |


I think the correct sequence should be as follows:

1. Start BACKUP command and stop it *after* make_global_read_lock_block_commit() 
is called but before global read lock is released. This is when all commits 
should be blocked.

2. In different connection, execute COMMIT. It should stop not on a breakpoint 
but because of the commit blocker being active.

3. Now, release the BACKUP breakpoint. BACKUP should complete (and the COMMIT 
will also finish) and resulting image should *not* contain data from the 
transaction.

Would replacing

con5: lock("commit_blocker_step_1");

with

con5: lock("commit_blocker_step_5");

ensure that order? Even better: add one more breakpoint "commit_blocker_step_4" 
inside block_commits() just after the call to 
make_global_read_lock_block_commit() and stop BACKUP on that breakpoint.

Best,
Rafal

cbell@stripped wrote:
> Below is the list of changes that have just been committed into a local
> 5.2 repository of cbell. When cbell does a push these changes will
> be propagated to the main repository and, within 24 hours after the
> push, to the public repository.
> For information on how to access the public repository
> see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
> 
> ChangeSet@stripped, 2007-11-02 15:27:41-04:00, cbell@mysql_cab_desk. +10 -0
>   WL#3956 : Online Backup: Commit Blocker
>   
>   This patch adds the code for the commit blocker and an elaborate test to test
>   the commit blocker while running transactions and non-transactions. See test
>   and worklog for more details.
>   
>   It also corrects the backup_snapshot test for use with the commit blocker.
> 
>   mysql-test/r/backup_commit_blocker.result@stripped, 2007-11-02 15:27:35-04:00,
> cbell@mysql_cab_desk. +549 -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     New test results.
>     
> 
>   mysql-test/r/backup_commit_blocker.result@stripped, 2007-11-02 15:27:35-04:00,
> cbell@mysql_cab_desk. +0 -0
> 
>   mysql-test/r/backup_snapshot.result@stripped, 2007-11-02 15:27:28-04:00,
> cbell@mysql_cab_desk. +20 -18
>     WL#3956 : Online Backup: Commit Blocker
>     
>     New test results.
> 
>   mysql-test/t/backup_commit_blocker.test@stripped, 2007-11-02 15:27:35-04:00,
> cbell@mysql_cab_desk. +755 -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds a new test to test the commit blocker. It tests 3 transactions
>     in various states and 2 non-transactions in either in-progress or not-started
>     states. 
>     
>     
> 
>   mysql-test/t/backup_commit_blocker.test@stripped, 2007-11-02 15:27:35-04:00,
> cbell@mysql_cab_desk. +0 -0
> 
>   mysql-test/t/backup_snapshot.test@stripped, 2007-11-02 15:27:29-04:00,
> cbell@mysql_cab_desk. +62 -23
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch modifies test due to introduction of commit blocker. Statements
>     must be placed differently and additional locks were needed to preserve
>     test. 
>     
> 
>   sql/backup/be_default.cc@stripped, 2007-11-02 15:27:33-04:00, cbell@mysql_cab_desk. +1
> -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds a breakpoint for the commit blocker test.
>     
> 
>   sql/backup/data_backup.cc@stripped, 2007-11-02 15:27:34-04:00, cbell@mysql_cab_desk.
> +142 -1
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds the commit blocker algorithm as described in the worklog.
> 
>   sql/handler.cc@stripped, 2007-11-02 15:27:30-04:00, cbell@mysql_cab_desk. +5 -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds a breakpoint for the commit blocker test.
>     
> 
>   sql/sql_delete.cc@stripped, 2007-11-02 15:27:31-04:00, cbell@mysql_cab_desk. +7 -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds a breakpoint for the commit blocker test.
>     
> 
>   sql/sql_insert.cc@stripped, 2007-11-02 15:27:32-04:00, cbell@mysql_cab_desk. +7 -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds breakpoints for the commit blocker test.
>     
> 
>   sql/sql_parse.cc@stripped, 2007-11-02 15:27:32-04:00, cbell@mysql_cab_desk. +9 -0
>     WL#3956 : Online Backup: Commit Blocker
>     
>     This patch adds breakpoints for the commit blocker test.
>     
> 


> diff -Nrup a/mysql-test/r/backup_commit_blocker.result
> b/mysql-test/r/backup_commit_blocker.result
> --- /dev/null	Wed Dec 31 16:00:00 196900
> +++ b/mysql-test/r/backup_commit_blocker.result	2007-11-02 15:27:35 -04:00
> @@ -0,0 +1,549 @@
> +DROP DATABASE IF EXISTS bup_commit_blocker;
> +CREATE DATABASE bup_commit_blocker;
> +
> +Starting Test 1
> +
> +con1: Creating tables
> +CREATE TABLE bup_commit_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t2 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t3 (col_a CHAR(40)) ENGINE=INNODB;
> +con1: Loading data
> +INSERT INTO bup_commit_blocker.t1 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("05 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("05 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("05 Some data to test");
> +con1: Show that the new data doesn't exist before backup.
> +SELECT * FROM bup_commit_blocker.t1;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t2;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t3;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +con2: Get a transaction going and stop in the middle
> +Assumption (a): TRX in progress is not included in backup
> +BEGIN;
> +UPDATE bup_commit_blocker.t1 SET col_a = "con2: CHANGED" WHERE col_a LIKE '01%';
> +con3: Start a transaction and send commit after lock is taken
> +Assumption (b): TRX in commit is included in backup
> +BEGIN;
> +INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 04 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 05 Some data to test");
> +con5: Getting lock on commit blocker.
> +SELECT get_lock("commit_blocker_step_1", 0);
> +get_lock("commit_blocker_step_1", 0)
> +1
> +con1: Backing up database -- will block with lock
> +BACKUP DATABASE bup_commit_blocker TO "bup_commit_blocker.bak";
> +con5: Checking lock
> +con3: Starting commit -- will block with lock
> +COMMIT;
> +con5: Checking lock
> +con5: Getting lock on commit blocker.
> +SELECT get_lock("backup_commit_blocker", 0);
> +get_lock("backup_commit_blocker", 0)
> +1
> +con5: Checking lock
> +con5: Checking lock
> +con4: Starting begin -- will block with lock
> +Assumption (c): TRX not started is not included in backup
> +BEGIN;
> +con5: Checking lock
> +con5: Releasing lock
> +SELECT release_lock("backup_commit_blocker");
> +release_lock("backup_commit_blocker")
> +1
> +con2: Completing transaction
> +DELETE FROM bup_commit_blocker.t1 WHERE col_a LIKE '02%';
> +COMMIT;
> +con3: Completing transaction
> +UPDATE bup_commit_blocker.t3 SET col_a = "con4: 05 CHANGED" WHERE col_a LIKE '05%';
> +UPDATE bup_commit_blocker.t3 SET col_a = "con4: 06 CHANGED" WHERE col_a LIKE '06%';
> +COMMIT;
> +Backup Summary
> + header     =       36 bytes
> + meta-data  =      284 bytes
> + data       =      782 bytes
> +              --------------
> + total            1102 bytes
> +con1: Showing data after updates and backup
> +SELECT * FROM bup_commit_blocker.t1;
> +col_a
> +con2: CHANGED
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t2;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +con3: 04 Some data to test
> +con3: 05 Some data to test
> +SELECT * FROM bup_commit_blocker.t3;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +con4: 05 CHANGED
> +con1: Dropping the database
> +DROP TABLE bup_commit_blocker.t1;
> +DROP TABLE bup_commit_blocker.t2;
> +DROP TABLE bup_commit_blocker.t3;
> +con1: Restoring the database
> +RESTORE FROM "bup_commit_blocker.bak";
> +Restore Summary
> + header     =       36 bytes
> + meta-data  =      284 bytes
> + data       =      782 bytes
> +              --------------
> + total            1102 bytes
> +con1: Showing the data (no new data should be here).
> +SELECT * FROM bup_commit_blocker.t1;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t2;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +con3: 04 Some data to test
> +con3: 05 Some data to test
> +SELECT * FROM bup_commit_blocker.t3;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +
> +Verifying test 1 results:
> +
> +T1 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t1 WHERE col_a like 'con2%';
> +count(*)
> +0
> +T2 should have the changes after backup - count(*) = 2
> +SELECT count(*) FROM bup_commit_blocker.t2 WHERE col_a like 'con3%';
> +count(*)
> +2
> +T3 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t3 WHERE col_a like 'con4%';
> +count(*)
> +0
> +con1: Cleanup
> +DROP DATABASE bup_commit_blocker;
> +
> +Starting Test 2
> +
> +CREATE DATABASE bup_commit_blocker;
> +con1: Creating tables
> +CREATE TABLE bup_commit_blocker.t4 (col_a int) ENGINE=CSV;
> +CREATE TABLE bup_commit_blocker.t5 (col_a int) ENGINE=CSV;
> +con1: Loading data
> +INSERT INTO bup_commit_blocker.t4 VALUES (1), (2), (3), (4), (5);
> +INSERT INTO bup_commit_blocker.t5 VALUES (10), (20), (30), (40), (50);
> +con1: Show that the new data doesn't exist before backup.
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +1
> +2
> +3
> +4
> +5
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +50
> +con5: Getting lock on commit blocker.
> +SELECT get_lock("backup_commit_blocker", 0);
> +get_lock("backup_commit_blocker", 0)
> +1
> +con6: Starting non-trx in progress -- will block with lock
> +Assumption (d): non-TRX in progress is included in backup
> +DELETE FROM bup_commit_blocker.t4 WHERE col_a <= 2;
> +con5: Checking lock
> +con1: Backing up database -- will block with lock
> +BACKUP DATABASE bup_commit_blocker TO "bup_commit_blocker.bak";
> +con5: Getting lock on commit blocker.
> +SELECT get_lock("commit_blocker_step_4", 0);
> +get_lock("commit_blocker_step_4", 0)
> +1
> +con5: Checking lock
> +con7: Show that the statement in progress has executed before backup.
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +3
> +4
> +5
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +50
> +con7: Starting non-trx about to start -- will block with lock
> +Assumption (e): non-TRX not started is not included in backup
> +UPDATE bup_commit_blocker.t5 SET col_a = 333 WHERE col_a = 30;
> +con5: Checking lock
> +con5: Releasing locks
> +SELECT release_lock("commit_blocker_step_4");
> +release_lock("commit_blocker_step_4")
> +1
> +SELECT release_lock("backup_commit_blocker");
> +release_lock("backup_commit_blocker")
> +NULL
> +con6: Completing statement
> +con7: Completing statement
> +Backup Summary
> + header     =       32 bytes
> + meta-data  =      182 bytes
> + data       =       80 bytes
> +              --------------
> + total             294 bytes
> +con1: Showing data after updates and backup
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +3
> +4
> +5
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +333
> +10
> +20
> +40
> +50
> +con1: Dropping the database
> +DROP TABLE bup_commit_blocker.t4;
> +DROP TABLE bup_commit_blocker.t5;
> +con1: Restoring the database
> +RESTORE FROM "bup_commit_blocker.bak";
> +Restore Summary
> + header     =       32 bytes
> + meta-data  =      182 bytes
> + data       =       80 bytes
> +              --------------
> + total             294 bytes
> +con1: Showing the data (no new data should be here).
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +3
> +4
> +5
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +50
> +
> +Verifying test 2 results:
> +
> +T4 should have the changes after backup - count(*) = 3
> +SELECT count(*) FROM bup_commit_blocker.t4 WHERE col_a > 2;
> +count(*)
> +3
> +T5 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t5 WHERE col_a = 333;
> +count(*)
> +0
> +con1: Cleanup
> +DROP DATABASE bup_commit_blocker;
> +
> +Starting Test 3
> +
> +CREATE DATABASE bup_commit_blocker;
> +con1: Creating tables
> +CREATE TABLE bup_commit_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t2 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t3 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t4 (col_a int) ENGINE=CSV;
> +CREATE TABLE bup_commit_blocker.t5 (col_a int) ENGINE=CSV;
> +con1: Loading data
> +INSERT INTO bup_commit_blocker.t1 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("05 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("05 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("05 Some data to test");
> +INSERT INTO bup_commit_blocker.t4 VALUES (1), (2), (3), (4), (5);
> +INSERT INTO bup_commit_blocker.t5 VALUES (10), (20), (30), (40), (50);
> +con1: Show that the new data doesn't exist before backup.
> +SELECT * FROM bup_commit_blocker.t1;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t2;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t3;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +1
> +2
> +3
> +4
> +5
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +50
> +con2: Get a transaction going and stop in the middle
> +Assumption (a): TRX in progress is not included in backup
> +BEGIN;
> +UPDATE bup_commit_blocker.t1 SET col_a = "con2: CHANGED" WHERE col_a LIKE '01%';
> +con3: Start a transaction and send commit after lock is taken
> +Assumption (b): TRX in commit is included in backup
> +BEGIN;
> +INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 04 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 05 Some data to test");
> +con5: Getting lock on commit blocker.
> +SELECT get_lock("commit_blocker_step_1", 0);
> +get_lock("commit_blocker_step_1", 0)
> +1
> +con1: Backing up database -- will block with lock
> +BACKUP DATABASE bup_commit_blocker TO "bup_commit_blocker.bak";
> +con6: Starting non-trx in progress -- will block
> +Assumption (d): non-TRX in progress is included in backup
> +INSERT INTO bup_commit_blocker.t4 VALUES (31), (32), (33);
> +con5: Checking lock
> +con5: Checking lock
> +con3: Starting commit -- will block with lock
> +COMMIT;
> +con5: Checking lock
> +con5: Getting lock on commit blocker.
> +SELECT get_lock("backup_commit_blocker", 0);
> +get_lock("backup_commit_blocker", 0)
> +1
> +con5: Checking lock
> +con5: Checking lock
> +con4: Starting begin -- will block with lock
> +Assumption (c): TRX not started is not included in backup
> +BEGIN;
> +con5: Checking lock
> +con5: Checking lock
> +con7: Show that the statement in progress has executed before backup.
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +1
> +2
> +3
> +4
> +5
> +31
> +32
> +33
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +50
> +con7: Starting non-trx about to start -- will block with lock
> +Assumption (e): non-TRX not started is not included in backup
> +DELETE FROM bup_commit_blocker.t5 WHERE col_a = 50;
> +con5: Checking lock
> +con5: Releasing lock
> +SELECT release_lock("backup_commit_blocker");
> +release_lock("backup_commit_blocker")
> +1
> +con2: Completing transaction
> +DELETE FROM bup_commit_blocker.t2 WHERE col_a LIKE '02%';
> +COMMIT;
> +con3: Completing transaction
> +UPDATE bup_commit_blocker.t3 SET col_a = "con4: 05 CHANGED" WHERE col_a LIKE '05%';
> +UPDATE bup_commit_blocker.t3 SET col_a = "con4: 06 CHANGED" WHERE col_a LIKE '06%';
> +COMMIT;
> +con6: Completing statement
> +con7: Completing statement
> +Backup Summary
> + header     =       47 bytes
> + meta-data  =      464 bytes
> + data       =      912 bytes
> +              --------------
> + total            1423 bytes
> +con1: Showing data after updates and backup
> +SELECT * FROM bup_commit_blocker.t1;
> +col_a
> +con2: CHANGED
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t2;
> +col_a
> +01 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +con3: 04 Some data to test
> +con3: 05 Some data to test
> +SELECT * FROM bup_commit_blocker.t3;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +con4: 05 CHANGED
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +1
> +2
> +3
> +4
> +5
> +31
> +32
> +33
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +con1: Dropping the database
> +DROP TABLE bup_commit_blocker.t1;
> +DROP TABLE bup_commit_blocker.t2;
> +DROP TABLE bup_commit_blocker.t3;
> +DROP TABLE bup_commit_blocker.t4;
> +DROP TABLE bup_commit_blocker.t5;
> +con1: Restoring the database
> +RESTORE FROM "bup_commit_blocker.bak";
> +Restore Summary
> + header     =       47 bytes
> + meta-data  =      464 bytes
> + data       =      912 bytes
> +              --------------
> + total            1423 bytes
> +con1: Showing the data (no new data should be here).
> +SELECT * FROM bup_commit_blocker.t1;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t2;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +con3: 04 Some data to test
> +con3: 05 Some data to test
> +SELECT * FROM bup_commit_blocker.t3;
> +col_a
> +01 Some data to test
> +02 Some data to test
> +03 Some data to test
> +04 Some data to test
> +05 Some data to test
> +SELECT * FROM bup_commit_blocker.t4;
> +col_a
> +1
> +2
> +3
> +4
> +5
> +31
> +32
> +33
> +SELECT * FROM bup_commit_blocker.t5;
> +col_a
> +10
> +20
> +30
> +40
> +50
> +
> +Verifying test 3 results:
> +
> +T1 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t1 WHERE col_a like 'con2%';
> +count(*)
> +0
> +T2 should have the changes after backup - count(*) = 2
> +SELECT count(*) FROM bup_commit_blocker.t2 WHERE col_a like 'con3%';
> +count(*)
> +2
> +T3 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t3 WHERE col_a like 'con4%';
> +count(*)
> +0
> +T4 should have the changes after backup - count(*) = 3
> +SELECT count(*) FROM bup_commit_blocker.t4 WHERE col_a > 30;
> +count(*)
> +3
> +T5 should not have the changes after backup - count(*) = 1
> +SELECT count(*) FROM bup_commit_blocker.t5 WHERE col_a >= 50;
> +count(*)
> +1
> +con1: Cleanup
> +DROP DATABASE bup_commit_blocker;


> diff -Nrup a/mysql-test/r/backup_snapshot.result
> b/mysql-test/r/backup_snapshot.result
> --- a/mysql-test/r/backup_snapshot.result	2007-11-02 13:25:27 -04:00
> +++ b/mysql-test/r/backup_snapshot.result	2007-11-02 15:27:28 -04:00
> @@ -22,14 +22,25 @@ COUNT(*)
>  SELECT COUNT(*) FROM bup_snapshot.t2;
>  COUNT(*)
>  5
> -con2: Getting lock on driver.
> +con3: Getting lock on driver.
>  SELECT get_lock("backup_cs_locked", 100);
>  get_lock("backup_cs_locked", 100)
>  1
>  con1: Backing up database. Spawn this and continue...
>  BACKUP DATABASE bup_snapshot TO "bup_snapshot.bak";
> -con2: Wait until backup pauses then insert new data.
> +con3: Checking locks.
>  INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
> +con3: Checking locks.
> +con3: Release lock on driver.
> +SELECT release_lock("backup_cs_locked");
> +release_lock("backup_cs_locked")
> +1
> +Backup Summary
> + header     =       29 bytes
> + meta-data  =      181 bytes
> + data       =      310 bytes
> +              --------------
> + total             520 bytes
>  INSERT INTO bup_snapshot.t1 VALUES("- Yes");
>  INSERT INTO bup_snapshot.t1 VALUES("- Jethro Tull");
>  DELETE FROM bup_snapshot.t1 WHERE word LIKE '10%';
> @@ -42,16 +53,6 @@ word
>  SELECT COUNT(*) FROM bup_snapshot.t1;
>  COUNT(*)
>  12
> -con2: Release lock on driver.
> -SELECT release_lock("backup_cs_locked");
> -release_lock("backup_cs_locked")
> -1
> -Backup Summary
> - header     =       29 bytes
> - meta-data  =      181 bytes
> - data       =      310 bytes
> -              --------------
> - total             520 bytes
>  con1: Dropping the database
>  DROP TABLE bup_snapshot.t1;
>  con1: Restoring the database
> @@ -71,14 +72,19 @@ COUNT(*)
>  SELECT COUNT(*) FROM bup_snapshot.t2;
>  COUNT(*)
>  5
> -con2: Getting lock on driver.
> +con3: Getting lock on driver.
>  SELECT get_lock("backup_cs_reading", 100);
>  get_lock("backup_cs_reading", 100)
>  1
>  con1: Backing up database. Spawn this and continue...
>  BACKUP DATABASE bup_snapshot TO "bup_snapshot.bak";
> -con2: Wait until backup pauses then insert new data.
> +con3: Checking locks.
>  INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
> +con3: Checking locks.
> +con3: Release lock on driver.
> +SELECT release_lock("backup_cs_reading");
> +release_lock("backup_cs_reading")
> +1
>  INSERT INTO bup_snapshot.t1 VALUES("- Yes");
>  INSERT INTO bup_snapshot.t1 VALUES("- Jethro Tull");
>  DELETE FROM bup_snapshot.t1 WHERE word LIKE '10%';
> @@ -91,10 +97,6 @@ word
>  SELECT COUNT(*) FROM bup_snapshot.t1;
>  COUNT(*)
>  12
> -con2: Release lock on driver.
> -SELECT release_lock("backup_cs_reading");
> -release_lock("backup_cs_reading")
> -1
>  Backup Summary
>   header     =       29 bytes
>   meta-data  =      181 bytes

> diff -Nrup a/mysql-test/t/backup_commit_blocker.test
> b/mysql-test/t/backup_commit_blocker.test
> --- /dev/null	Wed Dec 31 16:00:00 196900
> +++ b/mysql-test/t/backup_commit_blocker.test	2007-11-02 15:27:35 -04:00
> @@ -0,0 +1,755 @@
> +#
> +# This test is for the commit blocker
> +# The goals of the test should be to ensure the following assumptions for
> +# the behaviour of the commit blocker hold true.
> +#
> +# a) transactions in progress are not committed until after the backup
> +# b) transactions that are committing are allowed to commit
> +# c) transactions that have not started are allowed to start but do not commit
> +# d) non-transaction statements in progress are allowed to finish
> +# e) non-transaction statements that have not started are blocked
> +#
> +# The results of the backup should show (based on statements above):
> +#
> +# a) Test result for this assumption: Not included in backup
> +# b) Test result for this assumption: Included in backup
> +# c) Test result for this assumption: Not included in backup
> +# d) Test result for this assumption: Included in backup
> +# e) Test result for this assumption: Not included in backup
> +#
> +# Note: the statements above assume statements that change data.
> +#
> +# The test shall run three sets of data manipulation statements. 
> +#
> +# 1) transactional statments only
> +# 2) non-transactional statements only
> +# 3) mix of both transactional and non-transactional statements
> +#
> +# TODO : Add a native driver to the test when one becomes available
> +#
> +# We use a breakpoint named "backup_commit_blocker" which is placed
> +# strategically in the code to allow the threads to pause at the 
> +# corresponding location for those goals above.
> +#
> +
> +--source include/have_innodb.inc
> +--source include/have_debug.inc
> +
> +--disable_warnings
> +DROP DATABASE IF EXISTS bup_commit_blocker;
> +--enable_warnings
> +
> +CREATE DATABASE bup_commit_blocker;
> +
> +#
> +# Connections used in this test
> +#
> +# con1 - used to create data, load data, and run the backup 
> +# con2 - used for setting up transactions in progress
> +# con3 - used for setting up transactions in commit
> +# con4 - used for setting up transactions about to start
> +# con5 - used for setting and releasing breakpoints
> +# con6 - used for setting up non-transactions in progress
> +# con7 - used for setting up non-transactions about to start
> +#
> +
> +connect (con1,localhost,root,,);
> +connect (con2,localhost,root,,);
> +connect (con3,localhost,root,,);
> +connect (con4,localhost,root,,);
> +connect (con5,localhost,root,,);
> +connect (con6,localhost,root,,);
> +connect (con7,localhost,root,,);
> +
> +connection con1;
> +
> +#
> +# Test 1 - transactional statements only
> +#
> +
> +--echo 
> +--echo Starting Test 1
> +--echo 
> +
> +#
> +# Test 1 sequence diagram (not UML)
> +#
> +#   con1     con2     con3     con4     con5
> +#  (setup)    |        |        |        |
> +#     |       |        |        |        |
> +#     |     BEGIN      |        |        |
> +#     |    UPDATE t1   |        |        |
> +#     |       |      BEGIN      |        |
> +#     |       |     INSERT t2   |        |
> +#     |       |     INSERT t2   |        |
> +#     |       |        |        |  lock("commit_blocker_step_1");
> +#   BACKUP    |        |        |        |
> +#     |       |        |        |  <wait for locks>
> +#     |       |      COMMIT     |        |
> +#     |       |        |        |  <wait for locks>
> +#     |       |        |        |  lock("backup_commit_blocker");
> +#     |       |        |        |  <wait for locks>
> +#     |       |        |      BEGIN      |
> +#     |       |        |        |  <wait for locks>
> +#     |       |        |        |  <release locks>
> +#     |    DELETE t1   |        |        |
> +#     |     COMMIT     |        |        |
> +#     |       |      <...>      |        |
> +#     |       |        |     UPDATE t3   |
> +#     |       |        |     COMMIT      |
> +#   <...>     |        |        |        |
> +# (results)   |        |        |        |
> +#
> +# Note: The resume of the commands is indicated with <...> and
> +#       may occur in any order.
> +#
> +
> +# Create transaction tables and load them with data.
> +--echo con1: Creating tables
> +CREATE TABLE bup_commit_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t2 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t3 (col_a CHAR(40)) ENGINE=INNODB;
> +
> +--echo con1: Loading data
> +INSERT INTO bup_commit_blocker.t1 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("05 Some data to test");
> +
> +INSERT INTO bup_commit_blocker.t2 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("05 Some data to test");
> +
> +INSERT INTO bup_commit_blocker.t3 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("05 Some data to test");
> +
> +--echo con1: Show that the new data doesn't exist before backup.
> +SELECT * FROM bup_commit_blocker.t1;
> +SELECT * FROM bup_commit_blocker.t2;
> +SELECT * FROM bup_commit_blocker.t3;
> +
> +connection con2;
> +
> +--echo con2: Get a transaction going and stop in the middle
> +--echo Assumption (a): TRX in progress is not included in backup
> +BEGIN;
> +  UPDATE bup_commit_blocker.t1 SET col_a = "con2: CHANGED" WHERE col_a LIKE '01%';
> +
> +connection con3;
> +
> +--echo con3: Start a transaction and send commit after lock is taken
> +--echo Assumption (b): TRX in commit is included in backup
> +BEGIN;
> +  INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 04 Some data to test");
> +  INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 05 Some data to test");
> +
> +connection con5;
> +
> +# Set the breakpoint for the commit blocker.
> +--echo con5: Getting lock on commit blocker.
> +SELECT get_lock("commit_blocker_step_1", 0);
> +
> +# Start the backup and allow it to break on lock.
> +
> +connection con1;
> +
> +#
> +# We must start the backup and allow it to gather the metadata first.
> +# We stop (with the lock) the backup after the metadata but before the
> +# commit blocker.
> +#
> +--echo con1: Backing up database -- will block with lock
> +send BACKUP DATABASE bup_commit_blocker TO "bup_commit_blocker.bak";
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: commit_blocker_step_1"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +connection con3;
> +
> +--echo con3: Starting commit -- will block with lock
> +send COMMIT;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: commit_blocker_step_1"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "COMMIT%";
> +--source include/wait_condition.inc
> +
> +# Set the breakpoint for the commit blocker.
> +--echo con5: Getting lock on commit blocker.
> +SELECT get_lock("backup_commit_blocker", 0);
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "COMMIT%";
> +--source include/wait_condition.inc
> +
> +connection con4;
> +
> +--echo con4: Starting begin -- will block with lock
> +--echo Assumption (c): TRX not started is not included in backup
> +send BEGIN;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BEGIN%";
> +--source include/wait_condition.inc
> +
> +--echo con5: Releasing lock
> +SELECT release_lock("backup_commit_blocker");
> +
> +# Reconnect to con2, con3, and con4 and allow them to finish.
> +
> +connection con2;
> +
> +--echo con2: Completing transaction
> +  DELETE FROM bup_commit_blocker.t1 WHERE col_a LIKE '02%';
> +COMMIT;
> +
> +connection con3;
> +--echo con3: Completing transaction
> +reap;
> +
> +connection con4;
> +reap;
> +  UPDATE bup_commit_blocker.t3 SET col_a = "con4: 05 CHANGED" WHERE col_a LIKE
> '05%';
> +  UPDATE bup_commit_blocker.t3 SET col_a = "con4: 06 CHANGED" WHERE col_a LIKE
> '06%';
> +COMMIT;
> +
> +# Reconnect to con1 and let backup finish.
> +
> +connection con1;
> +reap;
> +
> +# Now restore the database and then check to make sure the new rows
> +# were not backed up.
> +
> +# Do selects to show that all changes got applied.
> +--echo con1: Showing data after updates and backup
> +SELECT * FROM bup_commit_blocker.t1;
> +SELECT * FROM bup_commit_blocker.t2;
> +SELECT * FROM bup_commit_blocker.t3;
> +
> +--echo con1: Dropping the database
> +DROP TABLE bup_commit_blocker.t1;
> +DROP TABLE bup_commit_blocker.t2;
> +DROP TABLE bup_commit_blocker.t3;
> +
> +--echo con1: Restoring the database
> +RESTORE FROM "bup_commit_blocker.bak";
> +
> +--echo con1: Showing the data (no new data should be here).
> +SELECT * FROM bup_commit_blocker.t1;
> +SELECT * FROM bup_commit_blocker.t2;
> +SELECT * FROM bup_commit_blocker.t3;
> +
> +--echo
> +--echo Verifying test 1 results:
> +--echo
> +
> +--echo T1 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t1 WHERE col_a like 'con2%';
> +
> +--echo T2 should have the changes after backup - count(*) = 2
> +SELECT count(*) FROM bup_commit_blocker.t2 WHERE col_a like 'con3%';
> +
> +--echo T3 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t3 WHERE col_a like 'con4%';
> +
> +--echo con1: Cleanup
> +DROP DATABASE bup_commit_blocker;
> +
> +remove_file $MYSQLTEST_VARDIR/master-data/bup_commit_blocker.bak;
> +
> +#
> +# Test 2 - non-transactional statements only
> +#
> +
> +--echo 
> +--echo Starting Test 2
> +--echo 
> +
> +#
> +# Test 2 sequence diagram (not UML)
> +#
> +#   con1     con2     con3     con4     con5     con6       con7
> +#  (setup)    |        |        |        |        |          |
> +#     |       |        |        |        |        |          |
> +#     |       |        |        |  lock("backup_commit_blocker");
> +#     |       |        |        |        |    DELETE t4      |
> +#     |       |        |        |  <wait for locks>          |
> +#   BACKUP    |        |        |        |        |          |
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |        |  lock("commit_blocker_step_4");
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |        |    (results)    |          |
> +#     |       |        |        |        |        |       UPDATE t5
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |        |  <release locks>|          |
> +#   <...>     |        |        |        |      <...>      <...>
> +# (results)   |        |        |        |        |          |
> +#
> +# Note: The resume of the commands is indicated with <...> and
> +#       may occur in any order.
> +#
> +
> +CREATE DATABASE bup_commit_blocker;
> +
> +# Create a non-transaction table and load it with data.
> +--echo con1: Creating tables
> +CREATE TABLE bup_commit_blocker.t4 (col_a int) ENGINE=CSV;
> +CREATE TABLE bup_commit_blocker.t5 (col_a int) ENGINE=CSV;
> +
> +--echo con1: Loading data
> +INSERT INTO bup_commit_blocker.t4 VALUES (1), (2), (3), (4), (5);
> +INSERT INTO bup_commit_blocker.t5 VALUES (10), (20), (30), (40), (50);
> +
> +--echo con1: Show that the new data doesn't exist before backup.
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +# Set the breakpoint for the commit blocker.
> +--echo con5: Getting lock on commit blocker.
> +SELECT get_lock("backup_commit_blocker", 0);
> +
> +connection con6;
> +
> +--echo con6: Starting non-trx in progress -- will block with lock
> +--echo Assumption (d): non-TRX in progress is included in backup
> +send DELETE FROM bup_commit_blocker.t4 WHERE col_a <= 2;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "DELETE%";
> +--source include/wait_condition.inc
> +
> +connection con1;
> +
> +--echo con1: Backing up database -- will block with lock
> +send BACKUP DATABASE bup_commit_blocker TO "bup_commit_blocker.bak";
> +
> +connection con5;
> +
> +# Set the breakpoint for the commit blocker.
> +#
> +# This allows the statement that was inprogress to finish and unblock the 
> +# backup which is waiting on open_and_lock_tables.
> +#
> +--echo con5: Getting lock on commit blocker.
> +SELECT get_lock("commit_blocker_step_4", 0);
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: commit_blocker_step_4"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +connection con7;
> +
> +--echo con7: Show that the statement in progress has executed before backup.
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +--echo con7: Starting non-trx about to start -- will block with lock
> +--echo Assumption (e): non-TRX not started is not included in backup
> +send UPDATE bup_commit_blocker.t5 SET col_a = 333 WHERE col_a = 30;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "Waiting for release of readlock"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "UPDATE%";
> +--source include/wait_condition.inc
> +
> +--echo con5: Releasing locks
> +SELECT release_lock("commit_blocker_step_4");
> +SELECT release_lock("backup_commit_blocker");
> +
> +# Reconnect to con6 and con7 and allow them to finish.
> +
> +connection con6;
> +
> +--echo con6: Completing statement
> +reap;
> +
> +connection con7;
> +--echo con7: Completing statement
> +reap;
> +
> +# Reconnect to con1 and let backup finish.
> +
> +connection con1;
> +reap;
> +
> +# Now restore the database and then check to make sure the new rows
> +# were not backed up.
> +
> +# Do selects to show that all changes got applied.
> +--echo con1: Showing data after updates and backup
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +--echo con1: Dropping the database
> +DROP TABLE bup_commit_blocker.t4;
> +DROP TABLE bup_commit_blocker.t5;
> +
> +--echo con1: Restoring the database
> +RESTORE FROM "bup_commit_blocker.bak";
> +
> +--echo con1: Showing the data (no new data should be here).
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +--echo
> +--echo Verifying test 2 results:
> +--echo
> +
> +--echo T4 should have the changes after backup - count(*) = 3
> +SELECT count(*) FROM bup_commit_blocker.t4 WHERE col_a > 2;
> +
> +--echo T5 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t5 WHERE col_a = 333;
> +
> +--echo con1: Cleanup
> +DROP DATABASE bup_commit_blocker;
> +
> +remove_file $MYSQLTEST_VARDIR/master-data/bup_commit_blocker.bak;
> +
> +#
> +# Test 3 - mix of both transactional and non-transactional statements
> +#
> +
> +--echo 
> +--echo Starting Test 3
> +--echo 
> +
> +#
> +# Test 3 sequence diagram (not UML)
> +#
> +#   con1     con2     con3     con4     con5     con6       con7
> +#  (setup)    |        |        |        |        |          |
> +#     |       |        |        |        |        |          |
> +#     |     BEGIN      |        |        |        |          |
> +#     |    UPDATE t1   |        |        |        |          |
> +#     |       |      BEGIN      |        |        |          |
> +#     |       |     INSERT t2   |        |        |          |
> +#     |       |     INSERT t2   |        |        |          |
> +#     |       |        |        |  lock("commit_blocker_step_1");
> +#   BACKUP    |        |        |        |        |          |
> +#     |       |        |        |        |     INSERT t4     |
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |      COMMIT     |        |        |          |
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |        |  lock("backup_commit_blocker");
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |      BEGIN      |        |          |
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |        |        |        |      (results)
> +#     |       |        |        |        |        |       DELETE t5
> +#     |       |        |        |  <wait for locks>          |
> +#     |       |        |        |  <release locks>|          |
> +#     |    DELETE t1   |        |        |        |          |
> +#     |     COMMIT     |        |        |        |          |
> +#     |       |      <...>      |        |        |          |
> +#     |       |        |     UPDATE t3   |        |          |
> +#     |       |        |     UPDATE t3   |        |          |
> +#     |       |        |     COMMIT      |        |          |
> +#   <...>     |        |        |        |      <...>      <...>
> +# (results)   |        |        |        |        |          |
> +#
> +# Note: The resume of the commands is indicated with <...> and
> +#       may occur in any order.
> +#
> +
> +CREATE DATABASE bup_commit_blocker;
> +
> +# Create tables and load them with data.
> +--echo con1: Creating tables
> +CREATE TABLE bup_commit_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t2 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t3 (col_a CHAR(40)) ENGINE=INNODB;
> +CREATE TABLE bup_commit_blocker.t4 (col_a int) ENGINE=CSV;
> +CREATE TABLE bup_commit_blocker.t5 (col_a int) ENGINE=CSV;
> +
> +--echo con1: Loading data
> +INSERT INTO bup_commit_blocker.t1 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t1 VALUES ("05 Some data to test");
> +
> +INSERT INTO bup_commit_blocker.t2 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t2 VALUES ("05 Some data to test");
> +
> +INSERT INTO bup_commit_blocker.t3 VALUES ("01 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("02 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("03 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("04 Some data to test");
> +INSERT INTO bup_commit_blocker.t3 VALUES ("05 Some data to test");
> +
> +INSERT INTO bup_commit_blocker.t4 VALUES (1), (2), (3), (4), (5);
> +INSERT INTO bup_commit_blocker.t5 VALUES (10), (20), (30), (40), (50);
> +
> +--echo con1: Show that the new data doesn't exist before backup.
> +SELECT * FROM bup_commit_blocker.t1;
> +SELECT * FROM bup_commit_blocker.t2;
> +SELECT * FROM bup_commit_blocker.t3;
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +connection con2;
> +
> +--echo con2: Get a transaction going and stop in the middle
> +--echo Assumption (a): TRX in progress is not included in backup
> +BEGIN;
> +  UPDATE bup_commit_blocker.t1 SET col_a = "con2: CHANGED" WHERE col_a LIKE '01%';
> +
> +connection con3;
> +
> +--echo con3: Start a transaction and send commit after lock is taken
> +--echo Assumption (b): TRX in commit is included in backup
> +BEGIN;
> +  INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 04 Some data to test");
> +  INSERT INTO bup_commit_blocker.t2 VALUES ("con3: 05 Some data to test");
> +
> +connection con5;
> +
> +# Set the breakpoint for the commit blocker.
> +--echo con5: Getting lock on commit blocker.
> +SELECT get_lock("commit_blocker_step_1", 0);
> +
> +# Start the backup and allow it to break on lock.
> +
> +connection con1;
> +
> +#
> +# We must start the backup and allow it to gather the metadata first.
> +# We stop (with the lock) the backup after the metadata but before the
> +# commit blocker.
> +#
> +--echo con1: Backing up database -- will block with lock
> +send BACKUP DATABASE bup_commit_blocker TO "bup_commit_blocker.bak";
> +
> +connection con6;
> +
> +--echo con6: Starting non-trx in progress -- will block
> +--echo Assumption (d): non-TRX in progress is included in backup
> +send INSERT INTO bup_commit_blocker.t4 VALUES (31), (32), (33);
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: commit_blocker_step_1"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: commit_blocker_step_1"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "INSERT INTO bup_commit_blocker.t4%";
> +--source include/wait_condition.inc
> +
> +connection con3;
> +
> +--echo con3: Starting commit -- will block with lock
> +send COMMIT;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: commit_blocker_step_1"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "COMMIT%";
> +--source include/wait_condition.inc
> +
> +# Set the breakpoint for the commit blocker.
> +--echo con5: Getting lock on commit blocker.
> +SELECT get_lock("backup_commit_blocker", 0);
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "COMMIT%";
> +--source include/wait_condition.inc
> +
> +connection con4;
> +
> +--echo con4: Starting begin -- will block with lock
> +--echo Assumption (c): TRX not started is not included in backup
> +send BEGIN;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BEGIN%";
> +--source include/wait_condition.inc
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +
> +let $wait_condition = SELECT state = "debug_sync_point: backup_commit_blocker"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +connection con7;
> +
> +--echo con7: Show that the statement in progress has executed before backup.
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +--echo con7: Starting non-trx about to start -- will block with lock
> +--echo Assumption (e): non-TRX not started is not included in backup
> +send DELETE FROM bup_commit_blocker.t5 WHERE col_a = 50;
> +
> +connection con5;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con5: Checking lock
> +let $wait_condition = SELECT state = "Waiting for release of readlock"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "DELETE%";
> +--source include/wait_condition.inc
> +
> +--echo con5: Releasing lock
> +SELECT release_lock("backup_commit_blocker");
> +
> +# Reconnect to con2, con3, con4, con6, and con7 and allow them to finish.
> +
> +connection con2;
> +
> +--echo con2: Completing transaction
> +  DELETE FROM bup_commit_blocker.t2 WHERE col_a LIKE '02%';
> +COMMIT;
> +
> +connection con3;
> +--echo con3: Completing transaction
> +reap;
> +
> +connection con4;
> +reap;
> +  UPDATE bup_commit_blocker.t3 SET col_a = "con4: 05 CHANGED" WHERE col_a LIKE
> '05%';
> +  UPDATE bup_commit_blocker.t3 SET col_a = "con4: 06 CHANGED" WHERE col_a LIKE
> '06%';
> +COMMIT;
> +
> +connection con6;
> +
> +--echo con6: Completing statement
> +reap;
> +
> +connection con7;
> +
> +--echo con7: Completing statement
> +reap;
> +
> +# Reconnect to con1 and let backup finish.
> +
> +connection con1;
> +reap;
> +
> +# Now restore the database and then check to make sure the new rows
> +# were not backed up.
> +
> +# Do selects to show that all changes got applied.
> +--echo con1: Showing data after updates and backup
> +SELECT * FROM bup_commit_blocker.t1;
> +SELECT * FROM bup_commit_blocker.t2;
> +SELECT * FROM bup_commit_blocker.t3;
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +--echo con1: Dropping the database
> +DROP TABLE bup_commit_blocker.t1;
> +DROP TABLE bup_commit_blocker.t2;
> +DROP TABLE bup_commit_blocker.t3;
> +DROP TABLE bup_commit_blocker.t4;
> +DROP TABLE bup_commit_blocker.t5;
> +
> +--echo con1: Restoring the database
> +RESTORE FROM "bup_commit_blocker.bak";
> +
> +--echo con1: Showing the data (no new data should be here).
> +SELECT * FROM bup_commit_blocker.t1;
> +SELECT * FROM bup_commit_blocker.t2;
> +SELECT * FROM bup_commit_blocker.t3;
> +SELECT * FROM bup_commit_blocker.t4;
> +SELECT * FROM bup_commit_blocker.t5;
> +
> +--echo
> +--echo Verifying test 3 results:
> +--echo
> +
> +--echo T1 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t1 WHERE col_a like 'con2%';
> +
> +--echo T2 should have the changes after backup - count(*) = 2
> +SELECT count(*) FROM bup_commit_blocker.t2 WHERE col_a like 'con3%';
> +
> +--echo T3 should not have the changes after backup - count(*) = 0
> +SELECT count(*) FROM bup_commit_blocker.t3 WHERE col_a like 'con4%';
> +
> +--echo T4 should have the changes after backup - count(*) = 3
> +SELECT count(*) FROM bup_commit_blocker.t4 WHERE col_a > 30;
> +
> +--echo T5 should not have the changes after backup - count(*) = 1
> +SELECT count(*) FROM bup_commit_blocker.t5 WHERE col_a >= 50;
> +
> +--echo con1: Cleanup
> +DROP DATABASE bup_commit_blocker;
> +
> +remove_file $MYSQLTEST_VARDIR/master-data/bup_commit_blocker.bak;
> +
> +

> diff -Nrup a/mysql-test/t/backup_snapshot.test b/mysql-test/t/backup_snapshot.test
> --- a/mysql-test/t/backup_snapshot.test	2007-11-02 13:25:28 -04:00
> +++ b/mysql-test/t/backup_snapshot.test	2007-11-02 15:27:29 -04:00
> @@ -30,6 +30,7 @@ CREATE DATABASE bup_snapshot;
>  
>  connect (con1,localhost,root,,);
>  connect (con2,localhost,root,,);
> +connect (con3,localhost,root,,);
>  
>  connection con1;
>  
> @@ -60,13 +61,13 @@ SELECT * FROM bup_snapshot.t1 WHERE word
>  SELECT COUNT(*) FROM bup_snapshot.t1;
>  SELECT COUNT(*) FROM bup_snapshot.t2;
>  
> -connection con2;
> +connection con3;
>  
>  #
>  # Test 1: Check for consistent read prior to open and lock tables
>  #
>  
> ---echo con2: Getting lock on driver.
> +--echo con3: Getting lock on driver.
>  SELECT get_lock("backup_cs_locked", 100);
>  
>  # While a consistent snapshot backup is executed,
> @@ -77,17 +78,42 @@ connection con1;
>  --echo con1: Backing up database. Spawn this and continue...
>  send BACKUP DATABASE bup_snapshot TO "bup_snapshot.bak";
>  
> +connection con3;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con3: Checking locks.
> +let $wait_condition = SELECT state = "debug_sync_point: backup_cs_locked"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE %";
> +--source include/wait_condition.inc
> +
> +# Start an insert now that CS has a transaction 
> +# The commit blocker will block this until the read lock of 
> +# the backup is released.
> +
>  connection con2;
>  
> ---echo con2: Wait until backup pauses then insert new data.
> +send INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
>  
> -# Must wait to know when backup has entered lock.
> -let $wait_condition = SELECT state = "debug_sync_point: backup_cs_locked"
> +connection con3;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con3: Checking locks.
> +let $wait_condition = SELECT count(*) = 1
>                        FROM INFORMATION_SCHEMA.PROCESSLIST
> -                      WHERE info LIKE "backup database %";
> +                      WHERE info LIKE "INSERT INTO bup_snapshot.t1%";
>  --source include/wait_condition.inc
>  
> -INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
> +--echo con3: Release lock on driver.
> +SELECT release_lock("backup_cs_locked");
> +
> +connection con1;
> +
> +reap;
> +
> +connection con2;
> +
> +reap;
>  INSERT INTO bup_snapshot.t1 VALUES("- Yes");
>  INSERT INTO bup_snapshot.t1 VALUES("- Jethro Tull");
>  DELETE FROM bup_snapshot.t1 WHERE word LIKE '10%';
> @@ -96,16 +122,11 @@ DELETE FROM bup_snapshot.t1 WHERE word L
>  SELECT * FROM bup_snapshot.t1 WHERE word LIKE '-%';
>  SELECT COUNT(*) FROM bup_snapshot.t1;
>  
> ---echo con2: Release lock on driver.
> -SELECT release_lock("backup_cs_locked");
> -
> -connection con1;
> -
> -reap;
> -
>  # Now restore the database and then check to make sure the new rows
>  # were not backed up.
>  
> +connection con1; 
> +
>  --echo con1: Dropping the database
>  DROP TABLE bup_snapshot.t1;
>  
> @@ -123,9 +144,9 @@ remove_file $MYSQLTEST_VARDIR/master-dat
>  # Test 2: Check for consistent read after open and lock tables
>  #
>  
> -connection con2;
> +connection con3;
>  
> ---echo con2: Getting lock on driver.
> +--echo con3: Getting lock on driver.
>  SELECT get_lock("backup_cs_reading", 100);
>  
>  # While a consistent snapshot backup is executed,
> @@ -136,17 +157,38 @@ connection con1;
>  --echo con1: Backing up database. Spawn this and continue...
>  send BACKUP DATABASE bup_snapshot TO "bup_snapshot.bak";
>  
> +connection con3;
> +
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con3: Checking locks.
> +let $wait_condition = SELECT state = "debug_sync_point: backup_cs_reading"
> +                      FROM INFORMATION_SCHEMA.PROCESSLIST
> +                      WHERE info LIKE "BACKUP DATABASE%";
> +--source include/wait_condition.inc
> +
> +# Start an insert now that CS has a transaction 
> +# The commit blocker will block this until the read lock of 
> +# the backup is released.
> +
>  connection con2;
>  
> ---echo con2: Wait until backup pauses then insert new data.
> +send INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
> +
> +connection con3;
>  
> -# Must wait to know when backup has entered lock.
> +# Wait for lock to be acquired and execution to reach breakpoint
> +--echo con3: Checking locks.
>  let $wait_condition = SELECT state = "debug_sync_point: backup_cs_reading"
>                        FROM INFORMATION_SCHEMA.PROCESSLIST
> -                      WHERE info LIKE "backup database %";
> +                      WHERE info LIKE "INSERT INTO bup_snapshot.t1%";
>  --source include/wait_condition.inc
>  
> -INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
> +--echo con3: Release lock on driver.
> +SELECT release_lock("backup_cs_reading");
> +
> +connection con2;
> +
> +reap;
>  INSERT INTO bup_snapshot.t1 VALUES("- Yes");
>  INSERT INTO bup_snapshot.t1 VALUES("- Jethro Tull");
>  DELETE FROM bup_snapshot.t1 WHERE word LIKE '10%';
> @@ -154,9 +196,6 @@ DELETE FROM bup_snapshot.t1 WHERE word L
>  --echo con2: Showing the data after inserts.
>  SELECT * FROM bup_snapshot.t1 WHERE word LIKE '-%';
>  SELECT COUNT(*) FROM bup_snapshot.t1;
> -
> ---echo con2: Release lock on driver.
> -SELECT release_lock("backup_cs_reading");
>  
>  connection con1;
>  


> diff -Nrup a/sql/backup/be_default.cc b/sql/backup/be_default.cc
> --- a/sql/backup/be_default.cc	2007-11-02 13:25:31 -04:00
> +++ b/sql/backup/be_default.cc	2007-11-02 15:27:33 -04:00
> @@ -137,6 +137,7 @@ result_t Backup::prelock()
>    DBUG_ENTER("Default_backup::open_tables");
>    lock_state= LOCK_IN_PROGRESS;
>    pthread_t th;
> +  BACKUP_BREAKPOINT("commit_blocker_step_1");
>    if (pthread_create(&th, &connection_attrib,
>                       backup_thread_for_locking, this))
>      SET_STATE_TO_ERROR_AND_DBUG_RETURN;
> diff -Nrup a/sql/backup/data_backup.cc b/sql/backup/data_backup.cc
> --- a/sql/backup/data_backup.cc	2007-11-02 13:55:48 -04:00
> +++ b/sql/backup/data_backup.cc	2007-11-02 15:27:34 -04:00
> @@ -358,6 +358,124 @@ int get_default_snapshot_tables(backup::
>  }
>  
>  /**
> +   Commit Blocker
> +
> +   The commit blocker ensures storage engines can't commit while in the 
> +   synchronization phase of Online Backup algorithm. This is needed to
> +   make sure that: 
> +
> +     1) backups are consistent between engines, and
> +     2) that the binlog position is consistent with the engine images.
> +
> +   REQUREMENTS  
> +     A transactional engine needs to block commits during the locking phase
> +   of backup kernel.  It can not block DDL for long time.
> +
> +   ALGORITHM
> +     The algortihm is implemented using five steps.
> +
> +     1) Preventing new write locks on tables -- lock_global_read_lock()
> +
> +        The idea is that non-transactional tables should not be modified.
> +        It is also a prerequisite of step 3.
> +
> +     2) Wait for existing locks to unlock -- close_cached_tables()
> +
> +        Ensures that no non-transactional table has any write lock. And thus
> +        no non-transactional engine can change any data (Note that the global
> +        read lock from step 1 is still in effect).
> +
> +     3) Prevents new commits and waits for running commits to finish --
> +        make_global_read_lock_block_commit()
> +
> +        This will make it impossible to enter commit phase in any transaction. 
> +        This will also wait for any ongoing commit to finish.
> +        When the function returns, no transaction is in its commit phase.
> +
> +     4) Read binlog position & do lock calls to all backup drivers
> +
> +        This step will read the binlog position and save it in the backup_info
> +        structure. This will occur between the lock() and unlock() calls in 
> +        the kernel.
> +
> +     5) unlock_global_read_lock()
> +
> +        This step unlocks the global read lock and thereby terminating the
> +        commit blocker.
> +  */
> +
> +
> +/**
> +   Block commits
> +  
> +   This method is used to initiate the first three steps of the commit blocker
> +   algorithm (global read lock, close cached tables, make global read lock
> +   block commits).
> +  
> +   @param  thd    (in) the current thread structure.
> +   @param  tables (in) list of tables to be backed-up.
> +  
> +   @returns 0 on success.
> +  */
> +int block_commits(THD *thd, TABLE_LIST *tables)
> +{
> +  DBUG_ENTER("block_commits()");
> +
> +  /*
> +    Step 1 - global read lock.
> +  */
> +  BACKUP_BREAKPOINT("commit_blocker_step_1");
> +  if (lock_global_read_lock(thd))
> +    DBUG_RETURN(1);                            
> +
> +  /*
> +    Step 2 - close cached tables.
> +
> +    Notice to Online Backup developers.
> +
> +    The method "close_cached_tables" as originally included in the commit
> +    blocker algorithm (see above) was omitted because there are no non-
> +    transactional tables that are not included in the existing default,
> +    consistent snapshot, and myisam drivers. This is only needed for engines
> +    that do not take lock tables. Thus, it should apply to write locked
> +    tables only and only to non-transactional engines.
> +
> +    BACKUP_BREAKPOINT("commit_blocker_step_2");
> +    result= close_cached_tables(thd, 0, tables); 
> +  */
> +
> +  /*
> +    Step 3 - make the global read lock to block commits.
> +  */
> +  BACKUP_BREAKPOINT("commit_blocker_step_3");
> +  if (make_global_read_lock_block_commit(thd)) 
> +  {
> +    /* Don't leave things in a half-locked state */
> +    unlock_global_read_lock(thd);
> +    DBUG_RETURN(1);
> +  }
> +  DBUG_RETURN(0);
> +}
> +
> +/**
> +   Unblock commits
> +  
> +   This method is used to terminate the commit blocker. It calls the last 
> +   step of the algorithm (unlock global read lock).
> +  
> +   @param  thd    (in) the current thread structure. 
> +
> +   @returns 0
> +  */
> +int unblock_commits(THD *thd)
> +{
> +  DBUG_ENTER("unblock_commits()");
> +  BACKUP_BREAKPOINT("commit_blocker_step_5");
> +  unlock_global_read_lock(thd);
> +  DBUG_RETURN(0);
> +}
> +
> +/**
>    Save data from tables being backed up.
>  
>    Function initializes and controls backup drivers which create the image
> @@ -366,8 +484,9 @@ int get_default_snapshot_tables(backup::
>  
>    @returns 0 on success.
>   */
> -int write_table_data(THD*, Backup_info &info, OStream &s)
> +int write_table_data(THD* thd, Backup_info &info, OStream &s)
>  {
> +  int error= 0;
>    my_bool def_or_snap_used= FALSE;  // Are default or snapshot used?
>    DBUG_ENTER("backup::write_table_data");
>  
> @@ -505,12 +624,34 @@ int write_table_data(THD*, Backup_info &
>  
>      // VP creation
>      DBUG_PRINT("backup/data",("-- SYNC PHASE --"));
> +
> +    /*
> +      Block commits.
> +
> +      TODO: Step 2 of the commit blocker has been skipped for this release.
> +      When it is included, developer needs to build a list of all of the 
> +      non-transactional tables and pass that to block_commits().
> +    */
> +    int error= 0;
> +    error= block_commits(thd, NULL);
> +    if (error)
> +      goto error;
> +
>      BACKUP_BREAKPOINT("data_lock");
>      if (sch.lock())
>        goto error;
>  
> +    BACKUP_BREAKPOINT("commit_blocker_step_4");
>      BACKUP_BREAKPOINT("data_unlock");
>      if (sch.unlock())
> +      goto error;
> +
> +    /*
> +      Unblock commits.
> +    */
> +    BACKUP_BREAKPOINT("backup_commit_blocker");
> +    error= unblock_commits(thd);
> +    if (error)
>        goto error;
>  
>      // get final data from drivers


> diff -Nrup a/sql/handler.cc b/sql/handler.cc
> --- a/sql/handler.cc	2007-09-27 16:36:56 -04:00
> +++ b/sql/handler.cc	2007-11-02 15:27:30 -04:00
> @@ -27,6 +27,7 @@
>  #include "rpl_filter.h"
>  #include <myisampack.h>
>  #include <errno.h>
> +#include "backup/debug.h"
>  
>  #ifdef WITH_PARTITION_STORAGE_ENGINE
>  #include "ha_partition.h"
> @@ -725,6 +726,10 @@ int ha_commit_trans(THD *thd, bool all)
>        goto end;
>      }
>  
> +    /*
> +      Breakpoints for backup testing.
> +    */
> +    BACKUP_BREAKPOINT("commit_blocker_step_1");
>      DBUG_EXECUTE_IF("crash_commit_before", abort(););
>  
>      /* Close all cursors that can not survive COMMIT */


> diff -Nrup a/sql/sql_delete.cc b/sql/sql_delete.cc
> --- a/sql/sql_delete.cc	2007-10-16 03:08:30 -04:00
> +++ b/sql/sql_delete.cc	2007-11-02 15:27:31 -04:00
> @@ -23,6 +23,7 @@
>  #include "sql_select.h"
>  #include "sp_head.h"
>  #include "sql_trigger.h"
> +#include "backup/debug.h"
>  
>  bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
>                    SQL_LIST *order, ha_rows limit, ulonglong options,
> @@ -381,6 +382,12 @@ cleanup:
>      if (ha_autocommit_or_rollback(thd,error >= 0))
>        error=1;
>    }
> +
> +  /*
> +    Breakpoints for backup testing.
> +  */
> +  if (!table->file->has_transactions())
> +    BACKUP_BREAKPOINT("backup_commit_blocker");
>  
>    if (thd->lock)
>    {


> diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
> --- a/sql/sql_insert.cc	2007-09-21 03:23:04 -04:00
> +++ b/sql/sql_insert.cc	2007-11-02 15:27:32 -04:00
> @@ -61,6 +61,7 @@
>  #include "sql_show.h"
>  #include "slave.h"
>  #include "rpl_mi.h"
> +#include "backup/debug.h"
>  
>  #ifndef EMBEDDED_LIBRARY
>  static bool delayed_get_table(THD *thd, TABLE_LIST *table_list);
> @@ -611,6 +612,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
>      if (open_and_lock_tables(thd, table_list))
>        DBUG_RETURN(TRUE);
>    }
> +
> +  /*
> +    Breakpoints for backup testing.
> +  */
> +  BACKUP_BREAKPOINT("backup_cs_reading");
> +  BACKUP_BREAKPOINT("commit_blocker_step_1");
>  
>    MYSQL_INSERT_START();
>    THD_SET_PROC_INFO(thd, "init");


> diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
> --- a/sql/sql_parse.cc	2007-09-14 05:20:44 -04:00
> +++ b/sql/sql_parse.cc	2007-11-02 15:27:32 -04:00
> @@ -27,6 +27,7 @@
>  #include "sp_cache.h"
>  #include "events.h"
>  #include "sql_trigger.h"
> +#include "backup/debug.h"
>  
>  /**
>    @defgroup Runtime_Environment Runtime Environment
> @@ -3506,6 +3507,10 @@ end_with_restore_list:
>                 xa_state_names[thd->transaction.xid_state.xa_state]);
>        break;
>      }
> +    /*
> +      Breakpoints for backup testing.
> +    */
> +    BACKUP_BREAKPOINT("backup_commit_blocker");
>      if (begin_trans(thd))
>        goto error;
>      send_ok(thd);
> @@ -3514,6 +3519,10 @@ end_with_restore_list:
>      if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE :
>                                lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
>        goto error;
> +    /*
> +      Breakpoints for backup testing.
> +    */
> +    BACKUP_BREAKPOINT("backup_commit_blocker");
>      send_ok(thd);
>      break;
>    case SQLCOM_ROLLBACK:
> 
> 
Thread
bk commit into 5.2 tree (cbell:1.2612)cbell2 Nov
  • Re: bk commit into 5.2 tree (cbell:1.2612)Rafal Somla5 Nov
    • RE: bk commit into 5.2 tree (cbell:1.2612)Chuck Bell5 Nov