List:Maria Storage Engine« Previous MessageNext Message »
From:Guilhem Bichot Date:July 9 2008 12:07pm
Subject:bzr commit into MySQL/Maria:mysql-maria branch (guilhem:2657)
View as plain text  
#At bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-maria/

 2657 Guilhem Bichot	2008-07-09
      - lifting a limit: INSERT|REPLACE SELECT and LOAD DATA always prevented versioning, now what do so is if
      the table is empty.
      - lifting another limit: versioning was disabled if table had more than one unique index
      - correcting test of statement-based binlogging, when converting read locks to TL_READ_NO_INSERT
modified:
  KNOWN_BUGS.txt
  mysql-test/r/maria-mvcc.result
  mysql-test/t/maria-mvcc.test
  sql/sql_parse.cc
  storage/maria/ha_maria.cc
  storage/maria/ma_open.c

per-file messages:
  KNOWN_BUGS.txt
    removing mostly fixed limitation (see ha_maria.cc)
  mysql-test/r/maria-mvcc.result
    result update
  mysql-test/t/maria-mvcc.test
    now when table is empty it does not do versioning, so test hung; inserting one row at start of the test,
    to enable versioning.
  sql/sql_parse.cc
    Maria team wrongly removed this "break", thanks Davi for noticing
  storage/maria/ha_maria.cc
    - We used to prevent versioning in INSERT/REPLACE SELECT and LOAD DATA, because the index rebuild done by
    bulk insert sometimes, is unsafe when versioning is on. Here we change that: in store_lock(), if the table is empty
    (which is required for index rebuild to be used), we disable versioning; in start_bulk_insert(), we don't do
    index rebuild if versioning is enabled.
    - Test for statement-based binlogging was incomplete: statement-based binlogging is on for this statement
    if binlog is open and statement has binlogging enabled and statement is not doing row-based binlogging
  storage/maria/ma_open.c
    Monty and I agreed that it's ok to have versioning on a table with more than one unique index: if an INSERT
    hits a duplicate key when inserting the second index' key, no other thread should be able to touch the 
    first index' just-inserted key, because that key has an uncommitted transaction id, so the first thread
    should have time to remove the first index' key.
=== modified file 'KNOWN_BUGS.txt'
--- a/KNOWN_BUGS.txt	2008-06-28 15:09:03 +0000
+++ b/KNOWN_BUGS.txt	2008-07-09 12:07:38 +0000
@@ -54,16 +54,7 @@ Known bugs that are planned to be fixed 
 =============================================
 
 LOCK TABLES .. WRITE CONCURRENT is mainly done for testing MVCC.  Don't
-use this in production.  Things that is not working if you are using
-this on a table:
-
-- INSERT/REPLACE ... SELECT on an empty table may cause crashes or
-  wrong results if someone else is doing writes on the table during repair
-  or someone is doing selects during the repair index phase.
-
-INSERT ... SELECT, REPLACE ... SELECT and LOAD DATA are blocking
-inserts and SELECT for the table.  They should only have to do this if
-the destination is empty (as then we are using fast index rebuild).
+use this in production.
 
 Missing features that is planned to fix before Beta
 ===================================================

=== modified file 'mysql-test/r/maria-mvcc.result'
--- a/mysql-test/r/maria-mvcc.result	2008-06-26 05:18:28 +0000
+++ b/mysql-test/r/maria-mvcc.result	2008-07-09 12:07:38 +0000
@@ -6,70 +6,78 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `i` int(11) DEFAULT NULL
 ) ENGINE=MARIA DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
+insert into t1 values (0);
 lock tables t1 write concurrent;
 insert into t1 values (1);
 insert into t1 values (2);
-/* should see 1 and 2 */
+/* should see 0, 1 and 2 */
 select i from t1;
 i
+0
 1
 2
 select count(*) from t1;
 count(*)
-2
-/* should see nothing */
+3
+/* should see 0 */
 select i from t1;
 i
+0
 select count(*) from t1;
 count(*)
-0
+1
 lock tables t1 write concurrent;
 insert into t1 values (3);
 insert into t1 values (4);
-/* should see 3 and 4 */
+/* should see 0, 3 and 4 */
 select i from t1;
 i
+0
 3
 4
 select count(*) from t1;
 count(*)
-2
+3
 unlock tables;
 lock tables t1 write concurrent;
 insert into t1 values (5);
-/* should see 3, 4 and 5 */
+/* should see 0, 3, 4 and 5 */
 select i from t1;
 i
+0
 3
 4
 5
 select count(*) from t1;
 count(*)
-3
+4
 lock tables t1 write concurrent;
-/* should see 3, 4 */
+/* should see 0, 3, 4 */
 select i from t1;
 i
+0
 3
 4
 select count(*) from t1;
 count(*)
-2
+3
 insert into t1 values (6);
-/* Should see 1, 2, 6 */
+/* Should see 0, 1, 2, 6 */
 select i from t1;
 i
+0
 1
 2
 6
 select count(*) from t1;
 count(*)
-3
+4
 unlock tables;
 lock tables t1 write concurrent;
-/* Should see 1, 2, 3, 4 and 6 */
+/* Should see 0, 1, 2, 3, 4 and 6 */
 select i from t1;
 i
+0
 1
 2
 3
@@ -77,20 +85,22 @@ i
 6
 select count(*) from t1;
 count(*)
-5
-/* should see 3, 4, 5 */
+6
+/* should see 0, 3, 4, 5 */
 select i from t1;
 i
+0
 3
 4
 5
 select count(*) from t1;
 count(*)
-3
+4
 unlock tables;
-/* should see 1, 2, 3, 4, 5, 6 */
+/* should see 0, 1, 2, 3, 4, 5, 6 */
 select i from t1;
 i
+0
 1
 2
 3
@@ -99,11 +109,12 @@ i
 6
 select count(*) from t1;
 count(*)
-6
+7
 unlock tables;
-/* should see 1, 2, 3, 4, 5, 6 */
+/* should see 0, 1, 2, 3, 4, 5, 6 */
 select i from t1;
 i
+0
 1
 2
 3
@@ -112,21 +123,23 @@ i
 6
 select count(*) from t1;
 count(*)
-6
+7
 insert into t1 values (7);
-/* should see 3, 4, 7 */
+/* should see 0, 3, 4, 7 */
 select i from t1;
 i
+0
 3
 4
 7
 select count(*) from t1;
 count(*)
-3
+4
 unlock tables;
-/* should see 1, 2, 3, 4, 5, 6, 7 */
+/* should see 0, 1, 2, 3, 4, 5, 6, 7 */
 select i from t1;
 i
+0
 1
 2
 3
@@ -136,7 +149,7 @@ i
 7
 select count(*) from t1;
 count(*)
-7
+8
 drop table t1;
 CREATE TABLE t1 (fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,    g GEOMETRY NOT NULL,   SPATIAL KEY(g) ) transactional=1 row_format=page engine=maria;
 lock tables t1 write concurrent, t1 as t2 write concurrent;

=== modified file 'mysql-test/t/maria-mvcc.test'
--- a/mysql-test/t/maria-mvcc.test	2008-06-26 05:18:28 +0000
+++ b/mysql-test/t/maria-mvcc.test	2008-07-09 12:07:38 +0000
@@ -15,71 +15,75 @@ connection con1;
 
 create table t1 (i int) engine=maria;
 show create table t1;
+
+# versioning is disabled when table is empty, so insert a row
+insert into t1 values (0);
+
 lock tables t1 write concurrent;
 insert into t1 values (1);
 insert into t1 values (2);
-/* should see 1 and 2 */
+/* should see 0, 1 and 2 */
 select i from t1;
 select count(*) from t1;
 
 connect (con2,localhost,root,,);
 connection con2;
-/* should see nothing */
+/* should see 0 */
 select i from t1;
 select count(*) from t1;
 lock tables t1 write concurrent;
 insert into t1 values (3);
 insert into t1 values (4);
-/* should see 3 and 4 */
+/* should see 0, 3 and 4 */
 select i from t1;
 select count(*) from t1;
 unlock tables;
 lock tables t1 write concurrent;
 insert into t1 values (5);
-/* should see 3, 4 and 5 */
+/* should see 0, 3, 4 and 5 */
 select i from t1;
 select count(*) from t1;
 
 connect (con3,localhost,root,,);
 connection con3;
 lock tables t1 write concurrent;
-/* should see 3, 4 */
+/* should see 0, 3, 4 */
 select i from t1;
 select count(*) from t1;
 
 connection con1;
 insert into t1 values (6);
-/* Should see 1, 2, 6 */
+/* Should see 0, 1, 2, 6 */
 select i from t1;
 select count(*) from t1;
 unlock tables;
 lock tables t1 write concurrent;
-/* Should see 1, 2, 3, 4 and 6 */
+/* Should see 0, 1, 2, 3, 4 and 6 */
 select i from t1;
 select count(*) from t1;
 
 connection con2;
-/* should see 3, 4, 5 */
+/* should see 0, 3, 4, 5 */
 select i from t1;
 select count(*) from t1;
 unlock tables;
-/* should see 1, 2, 3, 4, 5, 6 */
+/* should see 0, 1, 2, 3, 4, 5, 6 */
 select i from t1;
 select count(*) from t1;
 
 connection con1;
 unlock tables;
-/* should see 1, 2, 3, 4, 5, 6 */
+/* should see 0, 1, 2, 3, 4, 5, 6 */
 select i from t1;
 select count(*) from t1;
 
 connection con3;
 insert into t1 values (7);
-/* should see 3, 4, 7 */
+/* should see 0, 3, 4, 7 */
 select i from t1;
 select count(*) from t1;
 unlock tables;
-/* should see 1, 2, 3, 4, 5, 6, 7 */
+/* should see 0, 1, 2, 3, 4, 5, 6, 7 */
 select i from t1;
 select count(*) from t1;
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2008-05-29 18:39:25 +0000
+++ b/sql/sql_parse.cc	2008-07-09 12:07:38 +0000
@@ -2154,6 +2154,7 @@ mysql_execute_command(THD *thd)
     goto error;
 #endif
   }
+  break;
   case SQLCOM_SHOW_NEW_MASTER:
   {
     if (check_global_access(thd, REPL_SLAVE_ACL))

=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2008-07-09 09:02:27 +0000
+++ b/storage/maria/ha_maria.cc	2008-07-09 12:07:38 +0000
@@ -1812,9 +1812,12 @@ void ha_maria::start_bulk_insert(ha_rows
        a lot of rows.
        We should not do this for only a few rows as this is slower and
        we don't want to update the key statistics based of only a few rows.
+       Index file rebuild requires an exclusive lock, so if versioning is on
+       don't do it (see how ha_maria::store_lock() tries to predict repair).
     */
     if (file->state->records == 0 && can_enable_indexes &&
-        (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES))
+        (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES) &&
+        (file->lock.type == TL_WRITE))
     {
       /**
          @todo for a single-row INSERT SELECT, we will go into repair, which
@@ -2478,13 +2481,23 @@ THR_LOCK_DATA **ha_maria::store_lock(THD
         !thd->current_stmt_binlog_row_based &&
         (thd->lex->sql_command != SQLCOM_SELECT &&
          thd->lex->sql_command != SQLCOM_LOCK_TABLES) &&
+        (thd->options & OPTION_BIN_LOG) &&
         mysql_bin_log.is_open())
       lock_type= TL_READ_NO_INSERT;
     else if (lock_type == TL_WRITE_CONCURRENT_INSERT &&
-             (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
-              thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
-              thd->lex->sql_command == SQLCOM_LOAD))
+             (file->state->records == 0))
+    {
+      /*
+        Bulk insert may use repair, which will cause problems if other
+        threads try to read/insert to the table: disable versioning.
+        Note that our read of file->state->records is incorrect, as such
+        variable may have changed when we come to start_bulk_insert() (worse
+        case: we see != 0 so allow versioning, start_bulk_insert() sees 0 and
+        uses repair). This is prevented because start_bulk_insert() will not
+        try repair if we enabled versioning.
+      */
       lock_type= TL_WRITE;
+    }
     file->lock.type= lock_type;
   }
   *to++= &file->lock;

=== modified file 'storage/maria/ma_open.c'
--- a/storage/maria/ma_open.c	2008-07-09 09:02:27 +0000
+++ b/storage/maria/ma_open.c	2008-07-09 12:07:38 +0000
@@ -601,15 +601,6 @@ MARIA_HA *maria_open(const char *name, i
 	pos->null_bit=0;
 	pos->flag=0;					/* For purify */
 	pos++;
-
-        if ((share->keyinfo[i].flag & HA_NOSAME) && i != 0)
-        {
-          /*
-            We can't yet have versioning if there is more than one unique
-            key
-          */
-          versioning= 0;
-        }
       }
       for (i=0 ; i < uniques ; i++)
       {

Thread
bzr commit into MySQL/Maria:mysql-maria branch (guilhem:2657) Guilhem Bichot9 Jul