Commit c3246e4b authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.8 into 10.9

parents 0d55914d 6ac44ac3
--source include/have_utf32.inc
--source include/have_ucs2.inc
--source include/have_sequence.inc
EXECUTE IMMEDIATE SFORMAT('
CREATE VIEW v_bmp AS
SELECT
seq AS codepoint,
LPAD(HEX(seq),4,''0'') AS codepoint_hex4,
CONVERT(CHAR(seq USING utf32) USING {}) COLLATE {} AS c
FROM
seq_0_to_65535', @@character_set_connection, @@collation_connection);
SELECT COLLATION(c) FROM v_bmp LIMIT 1;
SELECT
codepoint_hex4,
HEX(CAST(LOWER(c) AS CHAR CHARACTER SET ucs2)),
HEX(CAST(UPPER(c) AS CHAR CHARACTER SET ucs2))
FROM v_bmp
WHERE BINARY(c)<>BINARY(LOWER(c)) OR BINARY(c)<>BINARY(UPPER(c));
DROP VIEW v_bmp;
--source include/have_utf32.inc
--source include/have_sequence.inc
EXECUTE IMMEDIATE SFORMAT('
CREATE VIEW v_supplementary AS
SELECT
seq AS codepoint,
LPAD(HEX(seq),8,''0'') AS codepoint_hex8,
CONVERT(CHAR(seq USING utf32) USING {}) COLLATE {} AS c
FROM
seq_65536_to_1114111', @@character_set_connection, @@collation_connection);
SELECT COLLATION(c) FROM v_supplementary LIMIT 1;
SELECT
codepoint_hex8,
HEX(CAST(LOWER(c) AS CHAR CHARACTER SET utf32)),
HEX(CAST(UPPER(c) AS CHAR CHARACTER SET utf32))
FROM v_supplementary
WHERE BINARY(c)<>BINARY(LOWER(c)) OR BINARY(c)<>BINARY(UPPER(c));
DROP VIEW v_supplementary;
--source include/have_utf32.inc
--source include/have_sequence.inc
EXECUTE IMMEDIATE SFORMAT('
CREATE VIEW v_bmp AS
SELECT
seq AS codepoint,
LPAD(HEX(seq),4,''0'') AS codepoint_hex4,
CONVERT(CHAR(seq USING utf32) USING {}) COLLATE {} AS c
FROM
seq_0_to_65535', @@character_set_connection, @@collation_connection);
SELECT COLLATION(c) FROM v_bmp LIMIT 1;
SELECT HEX(codepoint) FROM v_bmp WHERE HEX(WEIGHT_STRING(c))='FFFD';
SELECT
SUM(codepoint_hex4=HEX(WEIGHT_STRING(c))) AS count_bmp_weight_is_codepoint,
SUM(codepoint_hex4<>HEX(WEIGHT_STRING(c))) AS count_bmp_weight_is_not_codepoint
FROM v_bmp;
SELECT codepoint_hex4,HEX(WEIGHT_STRING(c))
FROM v_bmp
WHERE codepoint_hex4<>HEX(WEIGHT_STRING(c));
DROP VIEW v_bmp;
--source include/have_utf32.inc
--source include/have_sequence.inc
EXECUTE IMMEDIATE SFORMAT('
CREATE VIEW v_supplementary AS
SELECT
seq AS codepoint,
CONVERT(CHAR(seq USING utf32) USING {}) COLLATE {} AS c
FROM
seq_65536_to_1114111', @@character_set_connection, @@collation_connection);
SELECT COLLATION(c) FROM v_supplementary LIMIT 1;
SELECT
SUM(HEX(WEIGHT_STRING(c))<>'FFFD'),
SUM(HEX(WEIGHT_STRING(c))='FFFD')
FROM v_supplementary;
DROP VIEW v_supplementary;
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET collation_connection=ucs2_general_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET @@collation_connection=ucs2_general_ci;
--source include/ctype_unicode_ws_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET @@collation_connection=ucs2_general_mysql500_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET @@collation_connection=ucs2_general_mysql500_ci;
--source include/ctype_unicode_ws_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET @@collation_connection=ucs2_turkish_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET @@collation_connection=ucs2_unicode_520_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_general_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_general_ci;
--source include/ctype_unicode_ws_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_general_mysql500_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_general_mysql500_ci;
--source include/ctype_unicode_ws_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_turkish_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb3 COLLATE utf8mb3_unicode_520_ci;
--source include/ctype_unicode_casefold_bmp.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;
--source include/ctype_unicode_casefold_bmp.inc
--source include/ctype_unicode_casefold_supplementary.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;
--source include/ctype_unicode_ws_bmp.inc
--source include/ctype_unicode_ws_supplementary.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb4 COLLATE utf8mb4_turkish_ci;
--source include/ctype_unicode_casefold_bmp.inc
--source include/ctype_unicode_casefold_supplementary.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_520_ci;
--source include/ctype_unicode_casefold_bmp.inc
--source include/ctype_unicode_casefold_supplementary.inc
--echo #
--echo # End of 10.7 tests
--echo #
This diff is collapsed.
--echo #
--echo # Start of 10.7 tests
--echo #
--echo #
--echo # MDEV-30716 Wrong casefolding in xxx_unicode_520_ci for U+0700..U+07FF
--echo #
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
--source include/ctype_unicode_casefold_bmp.inc
--source include/ctype_unicode_casefold_supplementary.inc
--echo #
--echo # End of 10.7 tests
--echo #
SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET @save_dbug=@@GLOBAL.debug_dbug;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t1(f1 INT NOT NULL, f2 int not null,
f3 int generated always as (f2 * 2) VIRTUAL,
primary key(f1), INDEX (f3))ENGINE=InnoDB;
connect con1,localhost,root,,,;
InnoDB 0 transactions not purged
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
INSERT INTO t1(f1, f2) VALUES(1,2);
......@@ -18,5 +22,6 @@ commit;
disconnect con1;
disconnect con2;
connection default;
set global debug_dbug=default;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
SET GLOBAL debug_dbug=@save_dbug;
DROP TABLE t1;
--source include/have_innodb.inc
--source include/have_debug.inc
SET @save_frequency=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET @save_dbug=@@GLOBAL.debug_dbug;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t1(f1 INT NOT NULL, f2 int not null,
f3 int generated always as (f2 * 2) VIRTUAL,
primary key(f1), INDEX (f3))ENGINE=InnoDB;
connect(con1,localhost,root,,,);
--source ../innodb/include/wait_all_purged.inc
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
......@@ -26,5 +31,6 @@ commit;
disconnect con1;
disconnect con2;
connection default;
set global debug_dbug=default;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
SET GLOBAL debug_dbug=@save_dbug;
DROP TABLE t1;
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
InnoDB 0 transactions not purged
connect prevent_purge,localhost,root,,;
start transaction with consistent snapshot;
connect con_del_1,localhost,root,,;
......@@ -34,3 +37,4 @@ disconnect con_del_2;
connection default;
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_freq;
......@@ -7,6 +7,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL)
ROW_FORMAT=REDUNDANT ENGINE=InnoDB;
InnoDB 0 transactions not purged
connect prevent_purge,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
......@@ -19,7 +20,11 @@ UPDATE t1 SET b=4 WHERE a=3;
disconnect prevent_purge;
connection default;
InnoDB 0 transactions not purged
connection con1;
ROLLBACK;
disconnect con1;
connection default;
InnoDB 0 transactions not purged
FLUSH TABLE t1 FOR EXPORT;
Clustered index root page contents:
N_RECS=3; LEVEL=0
......
......@@ -3,6 +3,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB;
INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023;
connect con1,localhost,root,,;
InnoDB 0 transactions not purged
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
DELETE FROM t1 WHERE id=1788;
......
......@@ -9,12 +9,10 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency= 1;
CREATE PROCEDURE insert_n(start int, end int)
BEGIN
DECLARE i INT DEFAULT start;
START TRANSACTION;
WHILE i <= end do
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i;
SET i = i + 1;
END WHILE;
COMMIT;
END~~
CREATE FUNCTION num_pages_get()
RETURNS INT
......@@ -30,6 +28,7 @@ END~~
#
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,b), KEY (b,c))
ENGINE=InnoDB STATS_PERSISTENT=0;
InnoDB 0 transactions not purged
BEGIN;
SELECT * FROM t1;
a b c
......@@ -38,20 +37,24 @@ a b c
#
connect con2, localhost, root,,;
connection con2;
BEGIN;
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = NULL;
CALL insert_n(1, 50);;
connect con3, localhost, root,,;
connection con3;
BEGIN;
CALL insert_n(51, 100);;
connection con2;
COMMIT;
connection con3;
INSERT INTO t1 VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE c = NULL;
COMMIT;
connection default;
#
# Connect to default and record how many pages were accessed
# when selecting the record using the secondary key.
#
InnoDB 4 transactions not purged
InnoDB 2 transactions not purged
SET @num_pages_1 = num_pages_get();
SELECT * FROM t1 force index (b);
a b c
......
CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) ENGINE=InnoDB;
INSERT INTO t VALUES (10, "0123456789");
connection default;
BEGIN;
SELECT * FROM t WHERE c = 10 FOR UPDATE;
pk c
connect trx2, localhost,root,,;
BEGIN;
SET DEBUG_SYNC="lock_wait_start SIGNAL trx2_start_waiting";
SET DEBUG_SYNC="lock_wait_end SIGNAL trx2_wait_end WAIT_FOR trx2_cont_upd";
SET DEBUG_SYNC="lock_rec_store_on_page_infimum_end SIGNAL trx2_moved_locks WAIT_FOR trx2_cont";
UPDATE t SET c = NULL WHERE pk = 10;
connect trx3, localhost,root,,;
SET DEBUG_SYNC="now WAIT_FOR trx2_start_waiting";
SET innodb_lock_wait_timeout=1;
BEGIN;
SET DEBUG_SYNC="lock_wait_start SIGNAL trx3_start_waiting WAIT_FOR trx3_cont_waiting";
SET DEBUG_SYNC="lock_sys_t_cancel_enter SIGNAL trx3_cancel_enter WAIT_FOR trx3_cont_cancel_waiting";
UPDATE t SET c = "abcdefghij" WHERE pk = 10;
connection default;
SET DEBUG_SYNC="now WAIT_FOR trx3_start_waiting";
COMMIT;
SET DEBUG_SYNC="now WAIT_FOR trx2_wait_end";
SET DEBUG_SYNC="now SIGNAL trx3_cont_waiting";
SET DEBUG_SYNC="now WAIT_FOR trx3_cancel_enter";
SET DEBUG_SYNC="now SIGNAL trx2_cont_upd";
SET DEBUG_SYNC="now WAIT_FOR trx2_moved_locks";
SET DEBUG_SYNC="now SIGNAL trx3_cont_cancel_waiting";
SET DEBUG_SYNC="now SIGNAL trx2_cont";
disconnect trx2;
disconnect trx3;
connection default;
SET DEBUG_SYNC="RESET";
DROP TABLE t;
......@@ -3,8 +3,11 @@
source include/have_debug.inc;
source include/have_debug_sync.inc;
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
--source include/wait_all_purged.inc
--connect(prevent_purge,localhost,root,,)
start transaction with consistent snapshot;
......@@ -80,4 +83,5 @@ INSERT INTO t VALUES(30, 20);
SET DEBUG_SYNC = 'RESET';
DROP TABLE t;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_freq;
--source include/wait_until_count_sessions.inc
......@@ -14,6 +14,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL)
ROW_FORMAT=REDUNDANT ENGINE=InnoDB;
--source include/wait_all_purged.inc
--connect (prevent_purge,localhost,root)
START TRANSACTION WITH CONSISTENT SNAPSHOT;
......@@ -33,7 +34,12 @@ UPDATE t1 SET b=4 WHERE a=3;
# Initiate a full purge, which should reset the DB_TRX_ID except for a=3.
--source include/wait_all_purged.inc
# Initiate a ROLLBACK of the update, which should reset the DB_TRX_ID for a=3.
--connection con1
ROLLBACK;
--disconnect con1
--connection default
# Reset the DB_TRX_ID for the hidden ADD COLUMN metadata record.
--source include/wait_all_purged.inc
FLUSH TABLE t1 FOR EXPORT;
# The following is based on innodb.table_flags:
......
......@@ -9,6 +9,7 @@ CREATE TABLE t1(id INT PRIMARY key, val VARCHAR(16000)) ENGINE=InnoDB;
INSERT INTO t1 (id,val) SELECT 2*seq,'x' FROM seq_0_to_1023;
connect(con1,localhost,root,,);
source include/wait_all_purged.inc;
# Prevent purge.
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
......
......@@ -13,12 +13,10 @@ DELIMITER ~~;
CREATE PROCEDURE insert_n(start int, end int)
BEGIN
DECLARE i INT DEFAULT start;
START TRANSACTION;
WHILE i <= end do
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i;
SET i = i + 1;
END WHILE;
COMMIT;
END~~
CREATE FUNCTION num_pages_get()
......@@ -37,6 +35,7 @@ DELIMITER ;~~
--echo #
CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,b), KEY (b,c))
ENGINE=InnoDB STATS_PERSISTENT=0;
--source include/wait_all_purged.inc
BEGIN;
SELECT * FROM t1;
......@@ -45,18 +44,22 @@ SELECT * FROM t1;
--echo #
connect (con2, localhost, root,,);
connection con2;
BEGIN;
INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = NULL;
--send CALL insert_n(1, 50);
connect (con3, localhost, root,,);
connection con3;
BEGIN;
--send CALL insert_n(51, 100);
connection con2;
reap;
COMMIT;
connection con3;
reap;
INSERT INTO t1 VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE c = NULL;
COMMIT;
connection default;
......@@ -64,7 +67,7 @@ connection default;
--echo # Connect to default and record how many pages were accessed
--echo # when selecting the record using the secondary key.
--echo #
--let $wait_all_purged=4
--let $wait_all_purged=2
--source include/wait_all_purged.inc
SET @num_pages_1 = num_pages_get();
SELECT * FROM t1 force index (b);
......
--source include/have_innodb.inc
--source include/count_sessions.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
CREATE TABLE t (pk int PRIMARY KEY, c varchar(10)) ENGINE=InnoDB;
INSERT INTO t VALUES (10, "0123456789");
--connection default
BEGIN;
SELECT * FROM t WHERE c = 10 FOR UPDATE;
--connect(trx2, localhost,root,,)
BEGIN;
SET DEBUG_SYNC="lock_wait_start SIGNAL trx2_start_waiting";
SET DEBUG_SYNC="lock_wait_end SIGNAL trx2_wait_end WAIT_FOR trx2_cont_upd";
SET DEBUG_SYNC="lock_rec_store_on_page_infimum_end SIGNAL trx2_moved_locks WAIT_FOR trx2_cont";
#################
# We need to update clustered record without changing ordering fields and
# changing the size of non-ordering fields to cause locks moving from deleted
# record to infimum.
###
--send UPDATE t SET c = NULL WHERE pk = 10
--connect(trx3, localhost,root,,)
SET DEBUG_SYNC="now WAIT_FOR trx2_start_waiting";
#################
# The condition wariable waiting in lock_wait() must be finished by timeout
###
SET innodb_lock_wait_timeout=1;
BEGIN;
SET DEBUG_SYNC="lock_wait_start SIGNAL trx3_start_waiting WAIT_FOR trx3_cont_waiting";
SET DEBUG_SYNC="lock_sys_t_cancel_enter SIGNAL trx3_cancel_enter WAIT_FOR trx3_cont_cancel_waiting";
--send UPDATE t SET c = "abcdefghij" WHERE pk = 10
--connection default
SET DEBUG_SYNC="now WAIT_FOR trx3_start_waiting";
COMMIT;
SET DEBUG_SYNC="now WAIT_FOR trx2_wait_end";
SET DEBUG_SYNC="now SIGNAL trx3_cont_waiting";
SET DEBUG_SYNC="now WAIT_FOR trx3_cancel_enter";
SET DEBUG_SYNC="now SIGNAL trx2_cont_upd";
SET DEBUG_SYNC="now WAIT_FOR trx2_moved_locks";
#################
# If the bug is not fixed, there will be assertion failure here, because trx2
# moved trx3 lock from deleted record to infimum when trx3 tried to cancel the
# lock.
###
SET DEBUG_SYNC="now SIGNAL trx3_cont_cancel_waiting";
SET DEBUG_SYNC="now SIGNAL trx2_cont";
--disconnect trx2
--disconnect trx3
--connection default
SET DEBUG_SYNC="RESET";
DROP TABLE t;
--source include/wait_until_count_sessions.inc
......@@ -31,5 +31,33 @@ set DEBUG_SYNC= 'now SIGNAL fts_drop_index';
connection con1;
drop table t1, t2;
connection default;
set DEBUG_SYNC=RESET;
SET @@GLOBAL.debug_dbug = @saved_dbug;
disconnect con1;
#
# MDEV-25984 Assertion `max_doc_id > 0' failed in fts_init_doc_id()
#
call mtr.add_suppression("InnoDB: \\(Lock wait timeout\\) while getting next doc id for table `test`.`t1`");
CREATE TABLE t1(f1 CHAR(100), f2 INT, fulltext(f1))ENGINE=InnoDB;
INSERT INTO t1 VALUES("mariadb", 1), ("innodb", 1);
# restart
SET DEBUG_SYNC='innodb_rollback_after_fts_lock SIGNAL insert_dml WAIT_FOR ddl_continue';
ALTER TABLE t1 ADD UNIQUE INDEX(f2);
connect con1,localhost,root,,,;
SET DEBUG_SYNC='now WAIT_FOR insert_dml';
SET DEBUG_SYNC='fts_cmp_set_sync_doc_id_retry SIGNAL ddl_continue WAIT_FOR dml_finish';
INSERT INTO t1 VALUES("index", 2);
connection default;
ERROR 23000: Duplicate entry '1' for key 'f2'
SET DEBUG_SYNC="now SIGNAL dml_finish";
connection con1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` char(100) DEFAULT NULL,
`f2` int(11) DEFAULT NULL,
FULLTEXT KEY `f1` (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
connection default;
disconnect con1;
DROP TABLE t1;
set DEBUG_SYNC=RESET;
......@@ -129,8 +129,9 @@ test
select * from t1 where a like "te_t";
a
test
select * from t1 where match a against ("te*" in boolean mode)+0;
select * from t1 where match a against ("te*" in boolean mode);
a
test
drop table t1;
#
# Bug #49734: Crash on EXPLAIN EXTENDED UNION ... ORDER BY
......
......@@ -48,5 +48,33 @@ connection con1;
reap;
drop table t1, t2;
connection default;
set DEBUG_SYNC=RESET;
SET @@GLOBAL.debug_dbug = @saved_dbug;
disconnect con1;
--echo #
--echo # MDEV-25984 Assertion `max_doc_id > 0' failed in fts_init_doc_id()
--echo #
call mtr.add_suppression("InnoDB: \\(Lock wait timeout\\) while getting next doc id for table `test`.`t1`");
CREATE TABLE t1(f1 CHAR(100), f2 INT, fulltext(f1))ENGINE=InnoDB;
INSERT INTO t1 VALUES("mariadb", 1), ("innodb", 1);
--source include/restart_mysqld.inc
SET DEBUG_SYNC='innodb_rollback_after_fts_lock SIGNAL insert_dml WAIT_FOR ddl_continue';
SEND ALTER TABLE t1 ADD UNIQUE INDEX(f2);
connect(con1,localhost,root,,,);
SET DEBUG_SYNC='now WAIT_FOR insert_dml';
SET DEBUG_SYNC='fts_cmp_set_sync_doc_id_retry SIGNAL ddl_continue WAIT_FOR dml_finish';
send INSERT INTO t1 VALUES("index", 2);
connection default;
--error ER_DUP_ENTRY
reap;
SET DEBUG_SYNC="now SIGNAL dml_finish";
connection con1;
reap;
SHOW CREATE TABLE t1;
connection default;
disconnect con1;
DROP TABLE t1;
set DEBUG_SYNC=RESET;
......@@ -152,10 +152,7 @@ insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
select * from t1 where a like "abc%";
select * from t1 where a like "test%";
select * from t1 where a like "te_t";
# InnoDB_FTS: we don't support the postfix "+0"
# Work around MDEV-29871 (FIXME: remove this)
--echo select * from t1 where match a against ("te*" in boolean mode)+0;
--echo a
select * from t1 where match a against ("te*" in boolean mode);
drop table t1;
......
......@@ -2575,7 +2575,6 @@ fts_cmp_set_sync_doc_id(
que_t* graph = NULL;
fts_cache_t* cache = table->fts->cache;
char table_name[MAX_FULL_NAME_LEN];
retry:
ut_a(table->fts->doc_col != ULINT_UNDEFINED);
fts_table.suffix = "CONFIG";
......@@ -2583,7 +2582,8 @@ fts_cmp_set_sync_doc_id(
fts_table.type = FTS_COMMON_TABLE;
fts_table.table = table;
trx = trx_create();
trx= trx_create();
retry:
trx_start_internal(trx);
trx->op_info = "update the next FTS document id";
......@@ -2663,7 +2663,8 @@ fts_cmp_set_sync_doc_id(
"for table " << table->name;
fts_sql_rollback(trx);
if (error == DB_DEADLOCK) {
if (error == DB_DEADLOCK || error == DB_LOCK_WAIT_TIMEOUT) {
DEBUG_SYNC_C("fts_cmp_set_sync_doc_id_retry");
std::this_thread::sleep_for(FTS_DEADLOCK_RETRY_WAIT);
goto retry;
}
......
......@@ -9035,6 +9035,7 @@ inline bool rollback_inplace_alter_table(Alter_inplace_info *ha_alter_info,
ut_a(!lock_table_for_trx(dict_sys.sys_fields, ctx->trx, LOCK_X));
}
innodb_lock_wait_timeout= save_timeout;
DEBUG_SYNC_C("innodb_rollback_after_fts_lock");
row_mysql_lock_data_dictionary(ctx->trx);
ctx->rollback_instant();
innobase_rollback_sec_index(ctx->old_table, table,
......
......@@ -891,8 +891,8 @@ class lock_sys_t
/** Cancel a waiting lock request.
@tparam check_victim whether to check for DB_DEADLOCK
@param lock waiting lock request
@param trx active transaction
@param lock waiting lock request
@retval DB_SUCCESS if no lock existed
@retval DB_DEADLOCK if trx->lock.was_chosen_as_deadlock_victim was set
@retval DB_LOCK_WAIT if the lock was canceled */
......
......@@ -65,53 +65,44 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
/** length of the TRX_RSEG_HISTORY list (number of transactions) */
uint32_t history_size;
/** Last known transaction that has not been purged yet,
or 0 if everything has been purged. */
trx_id_t needs_purge;
private:
/** Reference counter to track rseg allocated transactions,
with SKIP and NEEDS_PURGE flags. */
/** Reference counter to track is_persistent() transactions,
with SKIP flag. */
std::atomic<uint32_t> ref;
/** Whether undo tablespace truncation is pending */
static constexpr uint32_t SKIP= 1;
/** Whether the log segment needs purge */
static constexpr uint32_t NEEDS_PURGE= 2;
/** Transaction reference count multiplier */
static constexpr uint32_t REF= 4;
static constexpr uint32_t REF= 2;
uint32_t ref_load() const { return ref.load(std::memory_order_relaxed); }
/** Set a bit in ref */
template<bool needs_purge> void ref_set()
/** Set the SKIP bit */
void ref_set_skip()
{
static_assert(SKIP == 1U << 0, "compatibility");
static_assert(NEEDS_PURGE == 1U << 1, "compatibility");
static_assert(SKIP == 1U, "compatibility");
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
if (needs_purge)
__asm__ __volatile__("lock btsl $1, %0" : "+m" (ref));
else
__asm__ __volatile__("lock btsl $0, %0" : "+m" (ref));
__asm__ __volatile__("lock btsl $0, %0" : "+m" (ref));
#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
_interlockedbittestandset(reinterpret_cast<volatile long*>(&ref),
needs_purge);
_interlockedbittestandset(reinterpret_cast<volatile long*>(&ref), 0);
#else
ref.fetch_or(needs_purge ? NEEDS_PURGE : SKIP, std::memory_order_relaxed);
ref.fetch_or(SKIP, std::memory_order_relaxed);
#endif
}
/** Clear a bit in ref */
template<bool needs_purge> void ref_reset()
void ref_reset_skip()
{
static_assert(SKIP == 1U << 0, "compatibility");
static_assert(NEEDS_PURGE == 1U << 1, "compatibility");
static_assert(SKIP == 1U, "compatibility");
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
if (needs_purge)
__asm__ __volatile__("lock btrl $1, %0" : "+m" (ref));
else
__asm__ __volatile__("lock btrl $0, %0" : "+m" (ref));
__asm__ __volatile__("lock btrl $0, %0" : "+m" (ref));
#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
_interlockedbittestandreset(reinterpret_cast<volatile long*>(&ref),
needs_purge);
_interlockedbittestandreset(reinterpret_cast<volatile long*>(&ref), 0);
#else
ref.fetch_and(needs_purge ? ~NEEDS_PURGE : ~SKIP,
std::memory_order_relaxed);
ref.fetch_and(~SKIP, std::memory_order_relaxed);
#endif
}
......@@ -125,26 +116,20 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
void destroy();
/** Note that undo tablespace truncation was started. */
void set_skip_allocation() { ut_ad(is_persistent()); ref_set<false>(); }
void set_skip_allocation() { ut_ad(is_persistent()); ref_set_skip(); }
/** Note that undo tablespace truncation was completed. */
void clear_skip_allocation()
{
ut_ad(is_persistent());
#if defined DBUG_OFF
ref_reset<false>();
ref_reset_skip();
#else
ut_d(auto r=) ref.fetch_and(~SKIP, std::memory_order_relaxed);
ut_ad(r == SKIP);
#endif
}
/** Note that the rollback segment requires purge. */
void set_needs_purge() { ref_set<true>(); }
/** Note that the rollback segment will not require purge. */
void clear_needs_purge() { ref_reset<true>(); }
/** @return whether the segment is marked for undo truncation */
bool skip_allocation() const { return ref_load() & SKIP; }
/** @return whether the segment needs purge */
bool needs_purge() const { return ref_load() & NEEDS_PURGE; }
/** Increment the reference count */
void acquire()
{ ut_d(auto r=) ref.fetch_add(REF); ut_ad(!(r & SKIP)); }
......
......@@ -246,12 +246,10 @@ trx_undo_free_at_shutdown(trx_t *trx);
@param[in,out] rseg rollback segment
@param[in] id rollback segment slot
@param[in] page_no undo log segment page number
@param[in,out] max_trx_id the largest observed transaction ID
@return the undo log
@retval nullptr on error */
trx_undo_t *
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
trx_id_t &max_trx_id);
trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no);
#endif /* !UNIV_INNOCHECKSUM */
......@@ -493,6 +491,8 @@ or 0 if the transaction has not been committed */
/** Before MariaDB 10.3.1, when purge did not reset DB_TRX_ID of
surviving user records, this used to be called TRX_UNDO_DEL_MARKS.
This field is redundant; it is only being read by some debug assertions.
The value 1 indicates that purge needs to process the undo log segment.
The value 0 indicates that all of it has been processed, and
trx_purge_free_segment() has been invoked, so the log is not safe to access.
......
This diff is collapsed.
This diff is collapsed.
......@@ -399,7 +399,7 @@ void trx_rseg_t::reinit(uint32_t page)
}
ut_ad(!is_referenced());
clear_needs_purge();
needs_purge= 0;
last_commit_and_offset= 0;
last_page_no= FIL_NULL;
curr_size= 1;
......@@ -407,10 +407,9 @@ void trx_rseg_t::reinit(uint32_t page)
/** Read the undo log lists.
@param[in,out] rseg rollback segment
@param[in,out] max_trx_id maximum observed transaction identifier
@param[in] rseg_header rollback segment header
@return error code */
static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
static dberr_t trx_undo_lists_init(trx_rseg_t *rseg,
const buf_block_t *rseg_header)
{
ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
......@@ -420,8 +419,8 @@ static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
uint32_t page_no= trx_rsegf_get_nth_undo(rseg_header, i);
if (page_no != FIL_NULL)
{
const trx_undo_t *undo= trx_undo_mem_create_at_db_start(rseg, i, page_no,
max_trx_id);
const trx_undo_t *undo=
trx_undo_mem_create_at_db_start(rseg, i, page_no);
if (!undo)
return DB_CORRUPTION;
rseg->curr_size+= undo->size;
......@@ -434,11 +433,9 @@ static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
/** Restore the state of a persistent rollback segment.
@param[in,out] rseg persistent rollback segment
@param[in,out] max_trx_id maximum observed transaction identifier
@param[in,out] mtr mini-transaction
@return error code */
static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
mtr_t *mtr)
static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr)
{
if (!rseg->space)
return DB_TABLESPACE_NOT_FOUND;
......@@ -454,8 +451,8 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
trx_id_t id= mach_read_from_8(TRX_RSEG + TRX_RSEG_MAX_TRX_ID +
rseg_hdr->page.frame);
if (id > max_trx_id)
max_trx_id= id;
if (id > rseg->needs_purge)
rseg->needs_purge= id;
const byte *binlog_name=
TRX_RSEG + TRX_RSEG_BINLOG_NAME + rseg_hdr->page.frame;
......@@ -491,7 +488,7 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
rseg->curr_size = mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE +
rseg_hdr->page.frame) + 1;
err= trx_undo_lists_init(rseg, max_trx_id, rseg_hdr);
err= trx_undo_lists_init(rseg, rseg_hdr);
if (err != DB_SUCCESS);
else if (auto len= flst_get_len(TRX_RSEG + TRX_RSEG_HISTORY +
rseg_hdr->page.frame))
......@@ -512,19 +509,16 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
trx_id_t id= mach_read_from_8(block->page.frame + node_addr.boffset +
TRX_UNDO_TRX_ID);
if (id > max_trx_id)
max_trx_id= id;
if (id > rseg->needs_purge)
rseg->needs_purge= id;
id= mach_read_from_8(block->page.frame + node_addr.boffset +
TRX_UNDO_TRX_NO);
if (id > max_trx_id)
max_trx_id= id;
if (id > rseg->needs_purge)
rseg->needs_purge= id;
rseg->set_last_commit(node_addr.boffset, id);
unsigned purge= mach_read_from_2(block->page.frame + node_addr.boffset +
TRX_UNDO_NEEDS_PURGE);
ut_ad(purge <= 1);
if (purge != 0)
rseg->set_needs_purge();
ut_ad(mach_read_from_2(block->page.frame + node_addr.boffset +
TRX_UNDO_NEEDS_PURGE) <= 1);
if (rseg->last_page_no != FIL_NULL)
/* There is no need to cover this operation by the purge
......@@ -597,9 +591,11 @@ dberr_t trx_rseg_array_init()
sys, rseg_id)),
page_no);
ut_ad(rseg.is_persistent());
if ((err = trx_rseg_mem_restore(
&rseg, max_trx_id, &mtr))
!= DB_SUCCESS) {
err = trx_rseg_mem_restore(&rseg, &mtr);
if (rseg.needs_purge > max_trx_id) {
max_trx_id = rseg.needs_purge;
}
if (err != DB_SUCCESS) {
mtr.commit();
break;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -4595,7 +4595,7 @@ static MY_UNICASE_CHARACTER u520p104[]={
MY_UNICASE_CHARACTER *my_unicase_pages_unicode520[4352]=
{
u520p00, u520p01, u520p02, u520p03, u520p04, u520p05, plane06, plane06,
u520p00, u520p01, u520p02, u520p03, u520p04, u520p05, plane06, plane07,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
u520p10, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, u520p1D, u520p1E, u520p1F,
......
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