diff --git a/mysql-test/suite/innodb/r/bug117237.result b/mysql-test/suite/innodb/r/bug117237.result new file mode 100644 index 00000000000..4ed15146ba3 --- /dev/null +++ b/mysql-test/suite/innodb/r/bug117237.result @@ -0,0 +1,37 @@ +CREATE PROCEDURE InsertIncrementData(IN num INT) +BEGIN +DECLARE current_id INT DEFAULT 0; +DECLARE current_k VARCHAR(700); +WHILE current_id <= num * 2 DO +SET current_k = LPAD(current_id, 700, '0'); +INSERT INTO t2 (id, k) VALUES (current_id, current_k); +SET current_id = current_id + 2; +END WHILE; +END | +create table t2 (id int primary key, k varchar(700), unique key k_1 (k)); +CALL InsertIncrementData(100); +# Case 1: be positioned at infimum +SET DEBUG_SYNC = 'RESET'; +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL s1 WAIT_FOR s2'; +ALTER TABLE t2 ADD unique key (k), ALGORITHM=INPLACE, LOCK=NONE; +SET DEBUG_SYNC = 'now WAIT_FOR s1'; +delete from t2 where id=44; +insert into t2 values (44, LPAD(44,700,'0')); +SET DEBUG_SYNC = 'now SIGNAL s2'; +Warnings: +Warning 1831 Duplicate index 'k' defined on the table 'test.t2'. This is deprecated and will be disallowed in a future release. +DROP TABLE t2; +create table t2 (id int primary key, k varchar(700), unique key k_1 (k)); +CALL InsertIncrementData(100); +# Case 2: be positioned at supremum +SET DEBUG_SYNC = 'RESET'; +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL s1 WAIT_FOR s2'; +ALTER TABLE t2 ADD unique key (k), ALGORITHM=INPLACE, LOCK=NONE; +SET DEBUG_SYNC = 'now WAIT_FOR s1'; +delete from t2 where id=44; +insert into t2 values (43, LPAD(44,700,'0')); +SET DEBUG_SYNC = 'now SIGNAL s2'; +Warnings: +Warning 1831 Duplicate index 'k' defined on the table 'test.t2'. This is deprecated and will be disallowed in a future release. +DROP TABLE t2; +DROP PROCEDURE InsertIncrementData; diff --git a/mysql-test/suite/innodb/t/bug117237.test b/mysql-test/suite/innodb/t/bug117237.test new file mode 100644 index 00000000000..16d7477001f --- /dev/null +++ b/mysql-test/suite/innodb/t/bug117237.test @@ -0,0 +1,65 @@ +--source include/have_debug.inc +connect (con1,localhost,root,,); + +# Prepare Data +DELIMITER |; + +CREATE PROCEDURE InsertIncrementData(IN num INT) +BEGIN + DECLARE current_id INT DEFAULT 0; + DECLARE current_k VARCHAR(700); + + WHILE current_id <= num * 2 DO + SET current_k = LPAD(current_id, 700, '0'); + INSERT INTO t2 (id, k) VALUES (current_id, current_k); + SET current_id = current_id + 2; + END WHILE; +END | + +DELIMITER ;| + +create table t2 (id int primary key, k varchar(700), unique key k_1 (k)); +CALL InsertIncrementData(100); + +--echo # Case 1: be positioned at infimum +connection default; +SET DEBUG_SYNC = 'RESET'; +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL s1 WAIT_FOR s2'; +--send ALTER TABLE t2 ADD unique key (k), ALGORITHM=INPLACE, LOCK=NONE + +connection con1; +SET DEBUG_SYNC = 'now WAIT_FOR s1'; +# Guarantee id=44 in online uk is the first row in a leaf page. +delete from t2 where id=44; +# The following row log will be positioned at infimum and cursor->low_match >= uk_num +insert into t2 values (44, LPAD(44,700,'0')); +SET DEBUG_SYNC = 'now SIGNAL s2'; + +connection default; +# Should not receive duplicate key error +--reap + +DROP TABLE t2; +create table t2 (id int primary key, k varchar(700), unique key k_1 (k)); +CALL InsertIncrementData(100); + +--echo # Case 2: be positioned at supremum +SET DEBUG_SYNC = 'RESET'; +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL s1 WAIT_FOR s2'; +--send ALTER TABLE t2 ADD unique key (k), ALGORITHM=INPLACE, LOCK=NONE + +connection con1; +SET DEBUG_SYNC = 'now WAIT_FOR s1'; +# Guarantee id=44 in online uk is the first row in a leaf page. +delete from t2 where id=44; +# The following row log will be positioned at supremum and cursor->up_match >= uk_num +insert into t2 values (43, LPAD(44,700,'0')); +SET DEBUG_SYNC = 'now SIGNAL s2'; + +connection default; +# Should not receive duplicate key error +--reap + +#Cleanup +DROP TABLE t2; +DROP PROCEDURE InsertIncrementData; \ No newline at end of file diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 1bbc5239d44..8fd203a83e3 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -3317,8 +3317,11 @@ static void row_log_apply_op_low( goto func_exit; case ROW_OP_INSERT: if (dict_index_is_unique(index) && - (cursor.up_match >= dict_index_get_n_unique(index) || - cursor.low_match >= dict_index_get_n_unique(index)) && + ((cursor.up_match >= dict_index_get_n_unique(index) && + !page_rec_is_supremum( + page_rec_get_next(btr_cur_get_rec(&cursor)))) || + (cursor.low_match >= dict_index_get_n_unique(index) && + !page_rec_is_infimum(btr_cur_get_rec(&cursor)))) && (!index->n_nullable || !dtuple_contains_null(entry))) { duplicate: /* Duplicate key */