mirror of
https://github.com/MariaDB/server.git
synced 2025-11-09 11:41:36 +03:00
MDEV-37199 UNIQUE KEY USING HASH accepting duplicate records
Server-level UNIQUE constraints (namely, WITHOUT OVERLAPS and USING HASH) only worked with InnoDB in REPEATABLE READ isolation mode, when the constraint was checked first and then the row was inserted or updated. Gap locks prevented race conditions when a concurrent connection could've also checked the constraint and inserted/updated a row at the same time. In READ COMMITTED there are no gap locks. To avoid race conditions, we now check the constraint *after* the row operation. This is enabled by the HA_CHECK_UNIQUE_AFTER_WRITE table flag that InnoDB sets in the READ COMMITTED transactions. Checking the constraint after the row operation is more complex. First, the constraint will see the current (inserted/updated) row, and needs to skip it. Second, IGNORE operations become tricky, as we need to revert the insert/update and continue statement execution. write_row() (INSERT IGNORE) is reverted with delete_row(). Conveniently it deletes the current row, that is, the last inserted row. update_row(a,b) (UPDATE IGNORE) is reverted with a reversed update, update_row(b,a). Conveniently, it updates the current row too. Except in InnoDB when the PK is updated - in this case InnoDB internally performs delete+insert, but does not move the cursor, so the "current" row is the deleted one and the reverse update doesn't work. This combination now throws an "unsupported" error and will be fixed in MDEV-37233
This commit is contained in:
254
mysql-test/main/long_unique_innodb_debug.result
Normal file
254
mysql-test/main/long_unique_innodb_debug.result
Normal file
@@ -0,0 +1,254 @@
|
||||
#
|
||||
# MDEV-37199 UNIQUE KEY USING HASH accepting duplicate records
|
||||
#
|
||||
## INSERT
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
# Keep a Read View open to prevent purge
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
# Create delete marked secondary index Record ('a', 10)
|
||||
insert t1 values(10, 'a');
|
||||
delete from t1;
|
||||
# Insert secondary index key ('a', 15) in the GAP between ('a', 10) and Supremum
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
insert t1 values(15, 'a');
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
# Insert secondary index key ('a', 5) in the GAP between Infimum and ('a', 10)
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(5, 'a');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 23000: Duplicate entry 'a' for key 'col2'
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
5 a
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## INSERT, row-level locking proof
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
# Keep a Read View open to prevent purge
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
# Create delete marked secondary index Record ('a', 10)
|
||||
insert t1 values(10, 'a');
|
||||
delete from t1;
|
||||
# Insert secondary index key ('a', 15) in the GAP between ('a', 10) and Supremum
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="ha_write_row_end SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
insert t1 values(15, 'a');
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
# Insert secondary index key ('a', 5) in the GAP between Infimum and ('a', 10)
|
||||
set session innodb_lock_wait_timeout= 1;
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(5, 'a');
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
15 a
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update t1 set col2='a' where col1=5;
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 23000: Duplicate entry 'a' for key 'col2'
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
5 b
|
||||
15 a
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## INSERT IGNORE
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, 'a');
|
||||
delete from t1;
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
insert ignore t1 values(15, 'a'), (16, 'b');
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(5, 'a');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
Warnings:
|
||||
Warning 1062 Duplicate entry 'a' for key 'col2'
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
5 a
|
||||
16 b
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE IGNORE
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
insert into t1 values( 9, 'd');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update ignore t1 set col2=chr(92+col1) where col1<=9;
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
5 b
|
||||
9 e
|
||||
15 a
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE modifying PK
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update t1 set col2='a', col1=4 where col1=5;
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 23000: Duplicate entry 'a' for key 'col2'
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
5 b
|
||||
15 a
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE IGNORE modifying PK
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
connect con1,localhost,root;
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
insert into t1 values( 9, 'd');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update ignore t1 set col2=chr(92+col1), col1=col1-1 where col1<=9;
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 42000: UPDATE IGNORE that modifies a primary key of a table with a UNIQUE constraint USING HASH is not currently supported
|
||||
connection default;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
commit;
|
||||
select * from t1;
|
||||
col1 col2
|
||||
5 b
|
||||
9 d
|
||||
15 a
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
# End of 10.6 tests
|
||||
239
mysql-test/main/long_unique_innodb_debug.test
Normal file
239
mysql-test/main/long_unique_innodb_debug.test
Normal file
@@ -0,0 +1,239 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-37199 UNIQUE KEY USING HASH accepting duplicate records
|
||||
--echo #
|
||||
|
||||
--echo ## INSERT
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
--echo # Keep a Read View open to prevent purge
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
--echo # Create delete marked secondary index Record ('a', 10)
|
||||
insert t1 values(10, 'a');
|
||||
delete from t1;
|
||||
--echo # Insert secondary index key ('a', 15) in the GAP between ('a', 10) and Supremum
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send insert t1 values(15, 'a')
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
--echo # Insert secondary index key ('a', 5) in the GAP between Infimum and ('a', 10)
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(5, 'a');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## INSERT, row-level locking proof
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
--echo # Keep a Read View open to prevent purge
|
||||
start transaction;
|
||||
select * from t1;
|
||||
|
||||
--connect con1,localhost,root
|
||||
--echo # Create delete marked secondary index Record ('a', 10)
|
||||
insert t1 values(10, 'a');
|
||||
delete from t1;
|
||||
--echo # Insert secondary index key ('a', 15) in the GAP between ('a', 10) and Supremum
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="ha_write_row_end SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send insert t1 values(15, 'a')
|
||||
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
--echo # Insert secondary index key ('a', 5) in the GAP between Infimum and ('a', 10)
|
||||
set session innodb_lock_wait_timeout= 1;
|
||||
set transaction isolation level read committed;
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
insert t1 values(5, 'a');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
|
||||
--connection con1
|
||||
--reap
|
||||
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update t1 set col2='a' where col1=5
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## INSERT IGNORE
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, 'a');
|
||||
delete from t1;
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send insert ignore t1 values(15, 'a'), (16, 'b')
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(5, 'a');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE IGNORE
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
insert into t1 values( 9, 'd');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update ignore t1 set col2=chr(92+col1) where col1<=9
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE modifying PK
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update t1 set col2='a', col1=4 where col1=5
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE IGNORE modifying PK
|
||||
create table t1 (
|
||||
col1 int primary key,
|
||||
col2 varchar(3000),
|
||||
unique (col2) using hash) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert into t1 values(10, 'a');
|
||||
delete from t1;
|
||||
insert into t1 values( 5, 'b');
|
||||
insert into t1 values(15, 'c');
|
||||
insert into t1 values( 9, 'd');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update ignore t1 set col2=chr(92+col1), col1=col1-1 where col1<=9
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set col2='a' where col1=15;
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
215
mysql-test/suite/period/r/innodb_debug.result
Normal file
215
mysql-test/suite/period/r/innodb_debug.result
Normal file
@@ -0,0 +1,215 @@
|
||||
#
|
||||
# MDEV-37199 UNIQUE KEY USING HASH accepting duplicate records
|
||||
#
|
||||
## INSERT
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
id s e
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
insert t1 values(10, date'2010-09-09', date'2010-11-10');
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-12');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 23000: Duplicate entry '10-2010-11-10-2010-09-09' for key 'id'
|
||||
connection default;
|
||||
select * from t1;
|
||||
id s e
|
||||
commit;
|
||||
select * from t1;
|
||||
id s e
|
||||
10 2010-10-10 2010-11-12
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
id s e
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update t1 set e=e + interval 2 month where s=date'2010-09-09';
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 23000: Duplicate entry '10-2010-11-10-2010-09-09' for key 'id'
|
||||
connection default;
|
||||
select * from t1;
|
||||
id s e
|
||||
commit;
|
||||
select * from t1;
|
||||
id s e
|
||||
10 2010-09-09 2010-09-10
|
||||
10 2010-10-10 2010-12-12
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## INSERT IGNORE
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
id s e
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
insert ignore t1 values(10, date'2010-09-09', date'2010-11-10'),(11, date'2010-09-09', date'2010-11-10');
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-12');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
Warnings:
|
||||
Warning 1062 Duplicate entry '10-2010-11-10-2010-09-09' for key 'id'
|
||||
connection default;
|
||||
select * from t1;
|
||||
id s e
|
||||
commit;
|
||||
select * from t1;
|
||||
id s e
|
||||
10 2010-10-10 2010-11-12
|
||||
11 2010-09-09 2010-11-10
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE IGNORE
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
id s e
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update ignore t1 set e=e + interval 2 month where s=date'2010-09-09';
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
connection default;
|
||||
select * from t1;
|
||||
id s e
|
||||
commit;
|
||||
select * from t1;
|
||||
id s e
|
||||
10 2010-09-09 2010-09-10
|
||||
10 2010-10-10 2010-12-12
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE modifying PK
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
primary key (id, p without overlaps)
|
||||
) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
id s e
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update t1 set e=e + interval 2 month where s=date'2010-09-09';
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 23000: Duplicate entry '10-2010-11-10-2010-09-09' for key 'PRIMARY'
|
||||
connection default;
|
||||
select * from t1;
|
||||
id s e
|
||||
commit;
|
||||
select * from t1;
|
||||
id s e
|
||||
10 2010-09-09 2010-09-10
|
||||
10 2010-10-10 2010-12-12
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
## UPDATE IGNORE modifying PK
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
primary key (id, p without overlaps)
|
||||
) engine=innodb;
|
||||
start transaction;
|
||||
select * from t1;
|
||||
id s e
|
||||
connect con1,localhost,root;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
update ignore t1 set e=e + interval 2 month where s=date'2010-09-09';
|
||||
connect con2,localhost,root;
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
connection con1;
|
||||
ERROR 42000: UPDATE IGNORE that modifies a primary key of a table with a UNIQUE constraint WITHOUT OVERLAPS is not currently supported
|
||||
connection default;
|
||||
select * from t1;
|
||||
id s e
|
||||
commit;
|
||||
select * from t1;
|
||||
id s e
|
||||
10 2010-09-09 2010-09-10
|
||||
10 2010-10-10 2010-12-12
|
||||
disconnect con1;
|
||||
disconnect con2;
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
# End of 10.6 tests
|
||||
208
mysql-test/suite/period/t/innodb_debug.test
Normal file
208
mysql-test/suite/period/t/innodb_debug.test
Normal file
@@ -0,0 +1,208 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-37199 UNIQUE KEY USING HASH accepting duplicate records
|
||||
--echo #
|
||||
|
||||
--echo ## INSERT
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send insert t1 values(10, date'2010-09-09', date'2010-11-10')
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-12');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update t1 set e=e + interval 2 month where s=date'2010-09-09'
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## INSERT IGNORE
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_ins_step_enter SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send insert ignore t1 values(10, date'2010-09-09', date'2010-11-10'),(11, date'2010-09-09', date'2010-11-10')
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-12');
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE IGNORE
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
unique(id, p without overlaps)
|
||||
) engine=innodb;
|
||||
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update ignore t1 set e=e + interval 2 month where s=date'2010-09-09'
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE modifying PK
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
primary key (id, p without overlaps)
|
||||
) engine=innodb;
|
||||
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update t1 set e=e + interval 2 month where s=date'2010-09-09'
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_DUP_ENTRY
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
--echo ## UPDATE IGNORE modifying PK
|
||||
create table t1 (
|
||||
id int, s date, e date,
|
||||
period for p(s,e),
|
||||
primary key (id, p without overlaps)
|
||||
) engine=innodb;
|
||||
|
||||
start transaction;
|
||||
select * from t1;
|
||||
--connect con1,localhost,root
|
||||
insert t1 values(10, date'2010-10-10', date'2010-11-11');
|
||||
delete from t1;
|
||||
insert t1 values(10, date'2010-09-09', date'2010-09-10');
|
||||
insert t1 values(10, date'2010-12-10', date'2010-12-12');
|
||||
set transaction isolation level read committed;
|
||||
set debug_sync="innodb_row_update_for_mysql_begin SIGNAL checked_duplicate WAIT_FOR do_insert";
|
||||
--send update ignore t1 set e=e + interval 2 month where s=date'2010-09-09'
|
||||
--connect con2,localhost,root
|
||||
set debug_sync="now WAIT_FOR checked_duplicate";
|
||||
set transaction isolation level read committed;
|
||||
update t1 set s=date'2010-10-10' where e=date'2010-12-12';
|
||||
set debug_sync="now SIGNAL do_insert";
|
||||
--connection con1
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
--reap
|
||||
--connection default
|
||||
select * from t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
--disconnect con1
|
||||
--disconnect con2
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
@@ -7413,6 +7413,8 @@ static bool long_unique_fields_differ(KEY *keyinfo, const uchar *other)
|
||||
int handler::check_duplicate_long_entry_key(const uchar *new_rec, uint key_no)
|
||||
{
|
||||
int result;
|
||||
/* Skip just written row in the case of HA_CHECK_UNIQUE_AFTER_WRITE */
|
||||
bool lax= (ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE) > 0;
|
||||
KEY *key_info= table->key_info + key_no;
|
||||
uchar ptr[HA_HASH_KEY_LENGTH_WITH_NULL];
|
||||
DBUG_ENTER("handler::check_duplicate_long_entry_key");
|
||||
@@ -7452,6 +7454,11 @@ int handler::check_duplicate_long_entry_key(const uchar *new_rec, uint key_no)
|
||||
{
|
||||
if (!long_unique_fields_differ(key_info, lookup_buffer))
|
||||
{
|
||||
if (lax)
|
||||
{
|
||||
lax= false;
|
||||
continue;
|
||||
}
|
||||
result= HA_ERR_FOUND_DUPP_KEY;
|
||||
table->file->lookup_errkey= key_no;
|
||||
lookup_handler->position(table->record[0]);
|
||||
@@ -7527,7 +7534,8 @@ int handler::ha_check_long_uniques(const uchar *old_rec, const uchar *new_rec)
|
||||
{
|
||||
if (int res= check_duplicate_long_entry_key(new_rec, i))
|
||||
{
|
||||
if (!old_rec && table->next_number_field)
|
||||
if (!old_rec && table->next_number_field &&
|
||||
!(ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE))
|
||||
if (int err= update_auto_increment())
|
||||
return err;
|
||||
return res;
|
||||
@@ -7548,7 +7556,8 @@ int handler::ha_check_overlaps(const uchar *old_data, const uchar* new_data)
|
||||
if (table->versioned() && !table->vers_end_field()->is_max())
|
||||
return 0;
|
||||
|
||||
const bool is_update= old_data != NULL;
|
||||
const bool after_write= ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE;
|
||||
const bool is_update= !after_write && old_data;
|
||||
uchar *record_buffer= lookup_buffer + table_share->max_unique_length
|
||||
+ table_share->null_fields;
|
||||
|
||||
@@ -7603,7 +7612,9 @@ int handler::ha_check_overlaps(const uchar *old_data, const uchar* new_data)
|
||||
key_part_map((1 << (key_parts - 1)) - 1),
|
||||
HA_READ_AFTER_KEY);
|
||||
|
||||
if (!error && is_update)
|
||||
if (!error)
|
||||
{
|
||||
if (is_update)
|
||||
{
|
||||
/* In case of update it could happen that the nearest neighbour is
|
||||
a record we are updating. It means, that there are no overlaps
|
||||
@@ -7616,6 +7627,9 @@ int handler::ha_check_overlaps(const uchar *old_data, const uchar* new_data)
|
||||
if (memcmp(ref, lookup_handler->ref, ref_length) == 0)
|
||||
error= lookup_handler->ha_index_next(record_buffer);
|
||||
}
|
||||
else if (after_write)
|
||||
error= lookup_handler->ha_index_next(record_buffer);
|
||||
}
|
||||
|
||||
if (!error && table->check_period_overlaps(key_info, new_data, record_buffer))
|
||||
error= HA_ERR_FOUND_DUPP_KEY;
|
||||
@@ -7738,7 +7752,8 @@ int handler::ha_write_row(const uchar *buf)
|
||||
});
|
||||
DBUG_ASSERT(table_share->tmp_table || m_lock_type == F_WRLCK);
|
||||
|
||||
if ((error= ha_check_inserver_constraints(NULL, buf)))
|
||||
if (!(ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE) &&
|
||||
(error= ha_check_inserver_constraints(NULL, buf)))
|
||||
goto err;
|
||||
|
||||
MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
@@ -7754,6 +7769,25 @@ int handler::ha_write_row(const uchar *buf)
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
if ((ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE) &&
|
||||
(error= ha_check_inserver_constraints(NULL, buf)))
|
||||
{
|
||||
if (lookup_handler != this) // INSERT IGNORE or REPLACE or ODKU
|
||||
{
|
||||
position(buf);
|
||||
int e= rnd_pos(lookup_buffer, ref);
|
||||
if (!e)
|
||||
{
|
||||
increment_statistics(&SSV::ha_delete_count);
|
||||
TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, MAX_KEY, e,
|
||||
{ e= delete_row(buf);})
|
||||
}
|
||||
if (e)
|
||||
error= e;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
rows_changed++;
|
||||
if (row_logging)
|
||||
{
|
||||
@@ -7782,7 +7816,8 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
|
||||
DBUG_ASSERT(new_data == table->record[0]);
|
||||
DBUG_ASSERT(old_data == table->record[1]);
|
||||
|
||||
if ((error= ha_check_inserver_constraints(old_data, new_data)))
|
||||
if (!(ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE) &&
|
||||
(error= ha_check_inserver_constraints(old_data, new_data)))
|
||||
return error;
|
||||
|
||||
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
@@ -7800,6 +7835,35 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if ((ha_table_flags() & HA_CHECK_UNIQUE_AFTER_WRITE) &&
|
||||
(error= ha_check_inserver_constraints(old_data, new_data)))
|
||||
{
|
||||
int e= 0;
|
||||
if (ha_thd()->lex->ignore)
|
||||
{
|
||||
/* hack: modifying PK is not supported for now, see MDEV-37233 */
|
||||
if (table->s->primary_key != MAX_KEY)
|
||||
{
|
||||
KEY *key= table->key_info + table->s->primary_key;
|
||||
KEY_PART_INFO *kp= key->key_part;
|
||||
KEY_PART_INFO *end= kp + key->user_defined_key_parts;
|
||||
for (; kp < end; kp++)
|
||||
if (bitmap_is_set(table->write_set, kp->fieldnr-1))
|
||||
{
|
||||
my_printf_error(ER_NOT_SUPPORTED_YET, "UPDATE IGNORE that "
|
||||
"modifies a primary key of a table with a UNIQUE constraint "
|
||||
"%s is not currently supported", MYF(0),
|
||||
table->s->long_unique_table ? "USING HASH" : "WITHOUT OVERLAPS");
|
||||
return HA_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
increment_statistics(&SSV::ha_update_count);
|
||||
TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, MAX_KEY, e,
|
||||
{ e= update_row(new_data, old_data);})
|
||||
}
|
||||
return e ? e : error;
|
||||
}
|
||||
|
||||
rows_changed++;
|
||||
if (row_logging)
|
||||
{
|
||||
|
||||
@@ -368,7 +368,9 @@ enum chf_create_flags {
|
||||
/* Implements SELECT ... FOR UPDATE SKIP LOCKED */
|
||||
#define HA_CAN_SKIP_LOCKED (1ULL << 61)
|
||||
|
||||
#define HA_LAST_TABLE_FLAG HA_CAN_SKIP_LOCKED
|
||||
#define HA_CHECK_UNIQUE_AFTER_WRITE (1ULL << 62)
|
||||
|
||||
#define HA_LAST_TABLE_FLAG HA_CHECK_UNIQUE_AFTER_WRITE
|
||||
|
||||
|
||||
/* bits in index_flags(index_number) for what you can do with index */
|
||||
|
||||
@@ -5071,7 +5071,7 @@ ha_innobase::table_flags() const
|
||||
called before prebuilt is inited. */
|
||||
|
||||
if (thd_tx_isolation(thd) <= ISO_READ_COMMITTED) {
|
||||
return(flags);
|
||||
return(flags | HA_CHECK_UNIQUE_AFTER_WRITE);
|
||||
}
|
||||
|
||||
return(flags | HA_BINLOG_STMT_CAPABLE);
|
||||
|
||||
Reference in New Issue
Block a user