Commit 81d3d3ac authored by Guilhem Bichot's avatar Guilhem Bichot

- lifting a limit: INSERT|REPLACE SELECT and LOAD DATA always prevented...

- 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

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.
parent 60b88ce4
......@@ -54,16 +54,7 @@ Known bugs that are planned to be fixed later
=============================================
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
===================================================
......
......@@ -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;
......
......@@ -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;
......
......@@ -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))
......
......@@ -1812,9 +1812,12 @@ void ha_maria::start_bulk_insert(ha_rows 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,
!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;
......
......@@ -601,15 +601,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
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++)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment