- 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.
This commit is contained in:
parent
60b88ce475
commit
81d3d3ac42
@ -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++)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user