diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-03-08 10:03:45 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-03-08 10:03:45 +0200 |
commit | e8a2a70cf869cf32a50144704646a5f34e8d7be9 (patch) | |
tree | a50505a6d936f15536368b3405e43260e0e8696c | |
parent | c8a18589dec9137730122ecc07e16c4164939988 (diff) | |
parent | af87186c1d3f9eeab73bc38b1faa51ba17fa8017 (diff) | |
download | mariadb-git-e8a2a70cf869cf32a50144704646a5f34e8d7be9.tar.gz |
Merge 10.7 into 10.8
46 files changed, 325 insertions, 374 deletions
diff --git a/mysql-test/main/innodb_mysql_sync.result b/mysql-test/main/innodb_mysql_sync.result index 46ed7d43830..7fe3bdbba18 100644 --- a/mysql-test/main/innodb_mysql_sync.result +++ b/mysql-test/main/innodb_mysql_sync.result @@ -131,6 +131,7 @@ connection default; DROP DATABASE db1; # Test 2: Primary index (implicit), should block writes. CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb; +INSERT INTO t1 VALUES(1, 2); SET DEBUG_SYNC= "alter_table_inplace_after_lock_downgrade SIGNAL manage WAIT_FOR query"; # Sending: ALTER TABLE t1 ADD UNIQUE INDEX(a), LOCK=SHARED; @@ -139,15 +140,16 @@ SET DEBUG_SYNC= "now WAIT_FOR manage"; USE test; SELECT * FROM t1; a b +1 2 # Sending: -UPDATE t1 SET a=NULL; +UPDATE t1 SET a=3; connection con2; # Waiting for SELECT to be blocked by the metadata lock on t1 SET DEBUG_SYNC= "now SIGNAL query"; connection default; # Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a) connection con1; -# Reaping: UPDATE t1 SET a=NULL +# Reaping: UPDATE t1 SET a=3 # Test 3: Primary index (explicit), should block writes. connection default; ALTER TABLE t1 DROP INDEX a; @@ -158,15 +160,16 @@ connection con1; SET DEBUG_SYNC= "now WAIT_FOR manage"; SELECT * FROM t1; a b +3 2 # Sending: -UPDATE t1 SET a=NULL; +UPDATE t1 SET a=4; connection con2; # Waiting for SELECT to be blocked by the metadata lock on t1 SET DEBUG_SYNC= "now SIGNAL query"; connection default; # Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a) connection con1; -# Reaping: UPDATE t1 SET a=NULL +# Reaping: UPDATE t1 SET a=4 # Test 4: Secondary unique index, should not block reads. connection default; SET DEBUG_SYNC= "alter_table_inplace_after_lock_downgrade SIGNAL manage WAIT_FOR query"; @@ -176,6 +179,7 @@ connection con1; SET DEBUG_SYNC= "now WAIT_FOR manage"; SELECT * FROM t1; a b +4 2 SET DEBUG_SYNC= "now SIGNAL query"; connection default; # Reaping: ALTER TABLE t1 ADD UNIQUE (b) diff --git a/mysql-test/main/innodb_mysql_sync.test b/mysql-test/main/innodb_mysql_sync.test index 4026080c4b4..466bcb360c5 100644 --- a/mysql-test/main/innodb_mysql_sync.test +++ b/mysql-test/main/innodb_mysql_sync.test @@ -176,6 +176,7 @@ DROP DATABASE db1; --echo # Test 2: Primary index (implicit), should block writes. CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb; +INSERT INTO t1 VALUES(1, 2); SET DEBUG_SYNC= "alter_table_inplace_after_lock_downgrade SIGNAL manage WAIT_FOR query"; --echo # Sending: --send ALTER TABLE t1 ADD UNIQUE INDEX(a), LOCK=SHARED @@ -185,13 +186,13 @@ SET DEBUG_SYNC= "now WAIT_FOR manage"; USE test; SELECT * FROM t1; --echo # Sending: ---send UPDATE t1 SET a=NULL +--send UPDATE t1 SET a=3 connection con2; --echo # Waiting for SELECT to be blocked by the metadata lock on t1 let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist WHERE state= 'Waiting for table metadata lock' - AND info='UPDATE t1 SET a=NULL'; + AND info='UPDATE t1 SET a=3'; --source include/wait_condition.inc SET DEBUG_SYNC= "now SIGNAL query"; @@ -200,7 +201,7 @@ connection default; --reap connection con1; ---echo # Reaping: UPDATE t1 SET a=NULL +--echo # Reaping: UPDATE t1 SET a=3 --reap --echo # Test 3: Primary index (explicit), should block writes. @@ -215,13 +216,13 @@ connection con1; SET DEBUG_SYNC= "now WAIT_FOR manage"; SELECT * FROM t1; --echo # Sending: ---send UPDATE t1 SET a=NULL +--send UPDATE t1 SET a=4 connection con2; --echo # Waiting for SELECT to be blocked by the metadata lock on t1 let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist WHERE state= 'Waiting for table metadata lock' - AND info='UPDATE t1 SET a=NULL'; + AND info='UPDATE t1 SET a=4'; --source include/wait_condition.inc SET DEBUG_SYNC= "now SIGNAL query"; @@ -230,7 +231,7 @@ connection default; --reap connection con1; ---echo # Reaping: UPDATE t1 SET a=NULL +--echo # Reaping: UPDATE t1 SET a=4 --reap --echo # Test 4: Secondary unique index, should not block reads. diff --git a/mysql-test/suite/federated/rpl.test b/mysql-test/suite/federated/rpl.test index 6ec4bec5a1a..cc94ea8b716 100644 --- a/mysql-test/suite/federated/rpl.test +++ b/mysql-test/suite/federated/rpl.test @@ -1,3 +1,4 @@ +source have_federatedx.inc; source include/have_binlog_format_row.inc; source include/master-slave.inc; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 1e38075de0d..eb1aba72162 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -14,7 +14,6 @@ GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081 GCF-939 : MDEV-21520 galera.GCF-939 MW-328A : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 MW-328B : MDEV-22666 galera.MW-328A MTR failed: "Semaphore wait has lasted > 600 seconds" and do not release port 16002 -MW-328D : MDEV-27550 ER_LOCK_DEADLOCK is gone after MDEV-27025 MW-329 : MDEV-19962 Galera test failure on MW-329 galera_applier_ftwrl_table_alter : MDEV-26502 : galera.galera_applier_ftwrl_table_alter MTR failed : Result content mismatch galera_as_slave_replication_bundle : MDEV-15785 OPTION_GTID_BEGIN is set in Gtid_log_event::do_apply_event() diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 0638dd1e3bc..123b9ea5885 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -12,6 +12,7 @@ GAL-501 : MDEV-24645 galera_3nodes.GAL-501 MTR failed: failed to open gcomm backend connection: 110 GCF-354 : MDEV-25614 Galera test failure on GCF-354 +galera_2_cluster : MDEV-22195 temporarily disabled due to issues to be fixed with MDEV-22195 galera_gtid_2_cluster : MDEV-23775 Galera test failure on galera_3nodes.galera_gtid_2_cluster galera_ist_gcache_rollover : MDEV-23578 WSREP: exception caused by message: {v=0,t=1,ut=255,o=4,s=0,sr=0,as=1,f=6,src=50524cfe,srcvid=view_id(REG,50524cfe,4),insvid=view_id(UNKNOWN,00000000,0),ru=00000000,r=[-1,-1],fs=75,nl=(} galera_load_data_ist : MDEV-24639 galera_3nodes.galera_load_data_ist MTR failed with SIGABRT: query 'reap' failed: 2013: Lost connection to server during query diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_bigtest.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_bigtest.result new file mode 100644 index 00000000000..d6b29060dc7 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_bigtest.result @@ -0,0 +1,14 @@ +SET @save_size=@@innodb_buffer_pool_size; +# +# MDEV-27891: Delayed SIGSEGV in InnoDB buffer pool resize +# after or during DROP TABLE +# +select @@innodb_buffer_pool_chunk_size; +@@innodb_buffer_pool_chunk_size +1048576 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL innodb_buffer_pool_size=256*1024*1024; +DROP TABLE t1; +SET GLOBAL innodb_buffer_pool_size=@@innodb_buffer_pool_size + @@innodb_buffer_pool_chunk_size; +# End of 10.6 tests +SET GLOBAL innodb_buffer_pool_size=@save_size; diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index d6229415d34..82230573c44 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -462,12 +462,27 @@ INSERT INTO t1 SET a=0, i=REPEAT('1', 10000); ROLLBACK; set DEBUG_SYNC='now SIGNAL go'; connection default; -disconnect con1; SELECT * FROM t1; a b c d e f g h i 1 2 3 4 5 6 7 8 test DROP TABLE t1; SET DEBUG_SYNC=RESET; +# +# MDEV-27962 Instant DDL downgrades the MDL when table is empty +# +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL)ENGINE=InnoDB; +SET DEBUG_SYNC="alter_table_inplace_after_lock_downgrade SIGNAL try_insert WAIT_FOR alter_progress"; +ALTER TABLE t1 ADD INDEX(f1), ADD INDEX(f2); +connection con1; +SET SESSION lock_wait_timeout=1; +SET DEBUG_SYNC="now WAIT_FOR try_insert"; +INSERT INTO t1 VALUES(1, 2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET DEBUG_SYNC="now SIGNAL alter_progress"; +disconnect con1; +connection default; +DROP TABLE t1; +SET DEBUG_SYNC=reset; # End of 10.4 tests # # MDEV-22867 Assertion instant.n_core_fields == n_core_fields diff --git a/mysql-test/suite/innodb/r/lock_delete_updated.result b/mysql-test/suite/innodb/r/lock_delete_updated.result new file mode 100644 index 00000000000..c2cd47b5dd9 --- /dev/null +++ b/mysql-test/suite/innodb/r/lock_delete_updated.result @@ -0,0 +1,20 @@ +CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t VALUES (3); +BEGIN; +connection default; +UPDATE t SET a = 2; +connect con1,localhost,root; +DELETE FROM t; +connection default; +UPDATE t SET a = 1; +COMMIT; +connection con1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +disconnect con1; +connection default; +# The above DELETE must delete all the rows in the table, so the +# following SELECT must show 0 rows. +SELECT count(*) FROM t; +count(*) +1 +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/lock_wait_conflict.result b/mysql-test/suite/innodb/r/lock_wait_conflict.result deleted file mode 100644 index 25d18c03ea1..00000000000 --- a/mysql-test/suite/innodb/r/lock_wait_conflict.result +++ /dev/null @@ -1,27 +0,0 @@ -# -# MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock -# -CREATE TABLE t (a INT PRIMARY KEY, b INT NOT NULL UNIQUE) ENGINE=InnoDB; -connect prevent_purge,localhost,root,,; -start transaction with consistent snapshot; -connection default; -INSERT INTO t VALUES (20,20); -DELETE FROM t WHERE b = 20; -connect con_ins,localhost,root,,; -SET DEBUG_SYNC = 'row_ins_sec_index_entry_dup_locks_created SIGNAL ins_set_locks WAIT_FOR ins_cont'; -INSERT INTO t VALUES(10, 20); -connect con_del,localhost,root,,; -SET DEBUG_SYNC = 'now WAIT_FOR ins_set_locks'; -SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL del_locked'; -DELETE FROM t WHERE b = 20; -connection default; -SET DEBUG_SYNC = 'now WAIT_FOR del_locked'; -SET DEBUG_SYNC = 'now SIGNAL ins_cont'; -connection con_ins; -disconnect con_ins; -connection con_del; -disconnect con_del; -disconnect prevent_purge; -connection default; -SET DEBUG_SYNC = 'RESET'; -DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/page_reorganize.result b/mysql-test/suite/innodb/r/page_reorganize.result index 1059fc78531..20e1600bd0d 100644 --- a/mysql-test/suite/innodb/r/page_reorganize.result +++ b/mysql-test/suite/innodb/r/page_reorganize.result @@ -25,3 +25,10 @@ f1 disconnect con1; connection default; drop table t1; +# +# MDEV-27993 Assertion failed in btr_page_reorganize_low() +# +CREATE TABLE t1(a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB; +SET DEBUG_DBUG = '+d,do_page_reorganize'; +INSERT INTO t1 VALUES(0,0); +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_bigtest.opt b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_bigtest.opt new file mode 100644 index 00000000000..72f055d3b58 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_bigtest.opt @@ -0,0 +1,2 @@ +--innodb-buffer-pool-chunk-size=1M +--loose-skip-innodb-disable-resize_buffer_pool_debug diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_bigtest.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_bigtest.test new file mode 100644 index 00000000000..db5da2924fa --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_bigtest.test @@ -0,0 +1,28 @@ +--source include/have_innodb.inc +--source include/big_test.inc + +SET @save_size=@@innodb_buffer_pool_size; + +let $wait_timeout = 60; +let $wait_condition = + SELECT SUBSTR(variable_value, 1, 30) = 'Completed resizing buffer pool' + FROM information_schema.global_status + WHERE variable_name = 'INNODB_BUFFER_POOL_RESIZE_STATUS'; + +--echo # +--echo # MDEV-27891: Delayed SIGSEGV in InnoDB buffer pool resize +--echo # after or during DROP TABLE +--echo # + +select @@innodb_buffer_pool_chunk_size; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL innodb_buffer_pool_size=256*1024*1024; +DROP TABLE t1; +--source include/wait_condition.inc +SET GLOBAL innodb_buffer_pool_size=@@innodb_buffer_pool_size + @@innodb_buffer_pool_chunk_size; +--source include/wait_condition.inc + +--echo # End of 10.6 tests + +SET GLOBAL innodb_buffer_pool_size=@save_size; +--source include/wait_condition.inc diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index 02464d4f100..f102185c27f 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -533,11 +533,28 @@ set DEBUG_SYNC='now SIGNAL go'; connection default; reap; -disconnect con1; SELECT * FROM t1; DROP TABLE t1; SET DEBUG_SYNC=RESET; +--echo # +--echo # MDEV-27962 Instant DDL downgrades the MDL when table is empty +--echo # +CREATE TABLE t1(f1 INT NOT NULL, f2 INT NOT NULL)ENGINE=InnoDB; +SET DEBUG_SYNC="alter_table_inplace_after_lock_downgrade SIGNAL try_insert WAIT_FOR alter_progress"; +send ALTER TABLE t1 ADD INDEX(f1), ADD INDEX(f2); +connection con1; +SET SESSION lock_wait_timeout=1; +SET DEBUG_SYNC="now WAIT_FOR try_insert"; +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES(1, 2); +SET DEBUG_SYNC="now SIGNAL alter_progress"; +disconnect con1; +connection default; +reap; +DROP TABLE t1; +SET DEBUG_SYNC=reset; + --echo # End of 10.4 tests --echo # diff --git a/mysql-test/suite/innodb/t/lock_delete_updated.test b/mysql-test/suite/innodb/t/lock_delete_updated.test new file mode 100644 index 00000000000..4621d5fcd2b --- /dev/null +++ b/mysql-test/suite/innodb/t/lock_delete_updated.test @@ -0,0 +1,34 @@ +--source include/have_innodb.inc +--source include/count_sessions.inc + +CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t VALUES (3); + +BEGIN; + +connection default; +UPDATE t SET a = 2; + +connect con1,localhost,root; +send DELETE FROM t; + +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Updating" and info = "DELETE FROM t"; +--source include/wait_condition.inc + +UPDATE t SET a = 1; +COMMIT; + +connection con1; +error ER_LOCK_DEADLOCK; +reap; +disconnect con1; + +connection default; +--echo # The above DELETE must delete all the rows in the table, so the +--echo # following SELECT must show 0 rows. +SELECT count(*) FROM t; +DROP TABLE t; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/lock_wait_conflict.test b/mysql-test/suite/innodb/t/lock_wait_conflict.test deleted file mode 100644 index 46a29e14b43..00000000000 --- a/mysql-test/suite/innodb/t/lock_wait_conflict.test +++ /dev/null @@ -1,60 +0,0 @@ ---source include/have_innodb.inc ---source include/count_sessions.inc ---source include/have_debug.inc ---source include/have_debug_sync.inc - ---echo # ---echo # MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock ---echo # - -# The test checks the ability to acquire exclusive record lock if the acquiring -# transaction already holds a shared lock on the record and another transaction -# is waiting for a lock. - -CREATE TABLE t (a INT PRIMARY KEY, b INT NOT NULL UNIQUE) ENGINE=InnoDB; - ---connect(prevent_purge,localhost,root,,) -start transaction with consistent snapshot; - ---connection default -INSERT INTO t VALUES (20,20); -DELETE FROM t WHERE b = 20; - ---connect(con_ins,localhost,root,,) -SET DEBUG_SYNC = 'row_ins_sec_index_entry_dup_locks_created SIGNAL ins_set_locks WAIT_FOR ins_cont'; -send -INSERT INTO t VALUES(10, 20); - ---connect(con_del,localhost,root,,) -SET DEBUG_SYNC = 'now WAIT_FOR ins_set_locks'; -SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL del_locked'; -############################################################################### -# This DELETE creates waiting ORDINARY X-lock for heap_no 2 as the record is -# delete-marked, this lock conflicts with ORDINARY S-lock set by the the last -# INSERT. After the last INSERT creates insert-intention lock on -# heap_no 2, this lock will conflict with waiting ORDINARY X-lock of this -# DELETE, what causes DEADLOCK error for this DELETE. -############################################################################### -send -DELETE FROM t WHERE b = 20; - ---connection default -SET DEBUG_SYNC = 'now WAIT_FOR del_locked'; -SET DEBUG_SYNC = 'now SIGNAL ins_cont'; - ---connection con_ins ---reap ---disconnect con_ins - ---connection con_del -# Without the fix, ER_LOCK_DEADLOCK would be reported here. ---reap ---disconnect con_del - ---disconnect prevent_purge - ---connection default - -SET DEBUG_SYNC = 'RESET'; -DROP TABLE t; ---source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/page_reorganize.test b/mysql-test/suite/innodb/t/page_reorganize.test index 7408353976d..c4e0160cb6d 100644 --- a/mysql-test/suite/innodb/t/page_reorganize.test +++ b/mysql-test/suite/innodb/t/page_reorganize.test @@ -53,4 +53,12 @@ connection default; drop table t1; +--echo # +--echo # MDEV-27993 Assertion failed in btr_page_reorganize_low() +--echo # +CREATE TABLE t1(a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB; +SET DEBUG_DBUG = '+d,do_page_reorganize'; +INSERT INTO t1 VALUES(0,0); +DROP TABLE t1; + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result index a64086c9802..daf552cde8b 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result @@ -289,3 +289,32 @@ ENGINE=InnoDB; ALTER TABLE t1 ADD c SERIAL; DROP TABLE t1; # End of 10.3 tests +# +# MDEV-27582 Fulltext DDL decrements the FTS_DOC_ID value +# +CREATE TABLE t1 ( +f1 INT NOT NULL PRIMARY KEY, +f2 VARCHAR(64), FULLTEXT ft(f2)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +connect con1,localhost,root,,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1 WHERE f1 = 2; +ALTER TABLE t1 DROP INDEX ft; +ALTER TABLE t1 ADD FULLTEXT INDEX ft (f2); +INSERT INTO t1 VALUES (3, 'innodb fts search'); +SET GLOBAL innodb_optimize_fulltext_only=ON; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SET GLOBAL innodb_ft_aux_table = 'test/t1'; +SELECT max(DOC_ID) FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +max(DOC_ID) +3 +SELECT * FROM t1 WHERE MATCH(f2) AGAINST("+innodb +search" IN BOOLEAN MODE); +f1 f2 +3 innodb fts search +DROP TABLE t1; +disconnect con1; +SET GLOBAL innodb_optimize_fulltext_only=OFF; +SET GLOBAL innodb_ft_aux_table = default; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.opt b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.opt index e6ae8d0fe0a..5d5cca1c6f2 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.opt +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.opt @@ -1 +1,2 @@ --enable-plugin-innodb-sys-tables +--innodb_ft_index_table diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test index e8a7d603750..1ed164492d5 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test @@ -357,3 +357,28 @@ ALTER TABLE t1 ADD c SERIAL; DROP TABLE t1; --echo # End of 10.3 tests + +--echo # +--echo # MDEV-27582 Fulltext DDL decrements the FTS_DOC_ID value +--echo # +CREATE TABLE t1 ( + f1 INT NOT NULL PRIMARY KEY, + f2 VARCHAR(64), FULLTEXT ft(f2)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +connect(con1,localhost,root,,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +DELETE FROM t1 WHERE f1 = 2; +ALTER TABLE t1 DROP INDEX ft; +ALTER TABLE t1 ADD FULLTEXT INDEX ft (f2); +INSERT INTO t1 VALUES (3, 'innodb fts search'); +SET GLOBAL innodb_optimize_fulltext_only=ON; +OPTIMIZE TABLE t1; +SET GLOBAL innodb_ft_aux_table = 'test/t1'; +SELECT max(DOC_ID) FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +SELECT * FROM t1 WHERE MATCH(f2) AGAINST("+innodb +search" IN BOOLEAN MODE); +DROP TABLE t1; +disconnect con1; +SET GLOBAL innodb_optimize_fulltext_only=OFF; +SET GLOBAL innodb_ft_aux_table = default; diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result index b899969d1d1..c62a992ceb1 100644 --- a/mysql-test/suite/versioning/r/update.result +++ b/mysql-test/suite/versioning/r/update.result @@ -283,6 +283,7 @@ connection default; update t1 set b = 'foo'; connection con1; update t1 set a = 'bar'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction disconnect con1; connection default; drop table t1; diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test index a80a8a7b714..8ef304f2de3 100644 --- a/mysql-test/suite/versioning/t/update.test +++ b/mysql-test/suite/versioning/t/update.test @@ -186,9 +186,7 @@ send update t1 set b = 'foo'; connection con1; let $wait_condition= select count(*) from information_schema.innodb_lock_waits; source include/wait_condition.inc; -# There must no be DEADLOCK here as con1 transaction already holds locks, and -# default's transaction lock is waiting, so the locks of the following "UPDATE" -# must not conflict with waiting lock. +error ER_LOCK_DEADLOCK; update t1 set a = 'bar'; disconnect con1; connection default; diff --git a/plugin/type_mysql_json/type.cc b/plugin/type_mysql_json/type.cc index d2d49b20229..7e6576e5df4 100644 --- a/plugin/type_mysql_json/type.cc +++ b/plugin/type_mysql_json/type.cc @@ -211,6 +211,6 @@ maria_declare_plugin(type_mysql_json) NULL, NULL, "0.1", - MariaDB_PLUGIN_MATURITY_BETA + MariaDB_PLUGIN_MATURITY_GAMMA } maria_declare_plugin_end; diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 667b57b0f63..4f499d8e577 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -525,10 +525,11 @@ then args="$args --user=$user" fi -if test -n "$group" -then - args="$args --group=$group" -fi +#To be enabled if/when we enable --group as an option to mysqld +#if test -n "$group" +#then +# args="$args --group=$group" +#fi if test -f "$ldata/mysql/user.frm" then diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 9ef1b0a6971..34a2de1c119 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -704,6 +704,7 @@ then if test "$user" != "root" -o $SET_USER = 1 then USER_OPTION="--user=$user" + # To be used if/when we enable --system-group as an option to mysqld GROUP_OPTION="--group=$group" fi if test -n "$open_files" diff --git a/sql/item_func.cc b/sql/item_func.cc index 511e7f34f3b..cbf25ddf791 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3480,6 +3480,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, thd->alloc(f_args.arg_count*sizeof(Item_result)))) { + err_exit: free_udf(u_d); DBUG_RETURN(TRUE); } @@ -3511,7 +3512,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, func->used_tables_and_const_cache_join(item); f_args.arg_type[i]=item->result_type(); } - if (!(buffers=new (thd->mem_root) String[arg_count]) || + buffers=new (thd->mem_root) String[arg_count]; + if (!buffers || !multi_alloc_root(thd->mem_root, &f_args.args, arg_count * sizeof(char *), &f_args.lengths, arg_count * sizeof(long), @@ -3520,10 +3522,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, &f_args.attributes, arg_count * sizeof(char *), &f_args.attribute_lengths, arg_count * sizeof(long), NullS)) - { - free_udf(u_d); - DBUG_RETURN(TRUE); - } + goto err_exit; } if (func->fix_length_and_dec()) DBUG_RETURN(TRUE); @@ -3591,8 +3590,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, { my_error(ER_CANT_INITIALIZE_UDF, MYF(0), u_d->name.str, init_msg_buff); - free_udf(u_d); - DBUG_RETURN(TRUE); + goto err_exit; } func->max_length=MY_MIN(initid.max_length,MAX_BLOB_WIDTH); func->set_maybe_null(initid.maybe_null); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 314221eccd9..8b3d1a6aefc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7494,16 +7494,15 @@ static bool mysql_inplace_alter_table(THD *thd, lock for prepare phase under LOCK TABLES in the same way as when exclusive lock is required for duration of the whole statement. */ - if (!ha_alter_info->mdl_exclusive_after_prepare && - (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK || - ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK || + if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK || + ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK || inplace_supported == HA_ALTER_INPLACE_COPY_LOCK || inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK || inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK || inplace_supported == HA_ALTER_INPLACE_INSTANT) && (thd->locked_tables_mode == LTM_LOCK_TABLES || thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) || - alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)) + alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE) { if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) goto cleanup; @@ -7636,7 +7635,8 @@ static bool mysql_inplace_alter_table(THD *thd, necessary only for prepare phase (unless we are not under LOCK TABLES) and user has not explicitly requested exclusive lock. */ - if ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK || + if (!ha_alter_info->mdl_exclusive_after_prepare && + (inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK || inplace_supported == HA_ALTER_INPLACE_COPY_LOCK || inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK || inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK) && diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 5185b90b137..f71f4e350fd 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3,7 +3,7 @@ Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2015, 2021, MariaDB Corporation. +Copyright (c) 2015, 2022, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -3501,6 +3501,7 @@ fail_err: << ib::hex(thr ? thr->graph->trx->id : 0) << ' ' << rec_printer(entry).str()); DBUG_EXECUTE_IF("do_page_reorganize", + if (n_recs) btr_page_reorganize(page_cursor, index, mtr);); /* Now, try the insert */ diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index 3d476fbac77..85a698bc875 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -298,7 +298,7 @@ static buf_buddy_free_t* buf_buddy_alloc_zip(ulint i) buf = UT_LIST_GET_FIRST(buf_pool.zip_free[i]); - if (buf_pool.curr_size < buf_pool.old_size + if (buf_pool.is_shrinking() && UT_LIST_GET_LEN(buf_pool.withdraw) < buf_pool.withdraw_target) { @@ -609,7 +609,7 @@ recombine: We may waste up to 15360*max_len bytes to free blocks (1024 + 2048 + 4096 + 8192 = 15360) */ if (UT_LIST_GET_LEN(buf_pool.zip_free[i]) < 16 - && buf_pool.curr_size >= buf_pool.old_size) { + && !buf_pool.is_shrinking()) { goto func_exit; } @@ -715,7 +715,7 @@ buf_buddy_realloc(void* buf, ulint size) void buf_buddy_condense_free() { mysql_mutex_assert_owner(&buf_pool.mutex); - ut_ad(buf_pool.curr_size < buf_pool.old_size); + ut_ad(buf_pool.is_shrinking()); for (ulint i = 0; i < UT_ARR_SIZE(buf_pool.zip_free); ++i) { buf_buddy_free_t* buf = diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index dbe7f9cbd2d..d6281073942 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1191,7 +1191,6 @@ bool buf_pool_t::create() for (size_t i= 0; i < UT_ARR_SIZE(zip_free); ++i) UT_LIST_INIT(zip_free[i], &buf_buddy_free_t::list); ulint s= curr_size; - old_size= s; s/= BUF_READ_AHEAD_PORTION; read_ahead_area= s >= READ_AHEAD_PAGES ? READ_AHEAD_PAGES @@ -1664,7 +1663,6 @@ inline void buf_pool_t::resize() #endif /* BTR_CUR_HASH_ADAPT */ mysql_mutex_lock(&mutex); - ut_ad(curr_size == old_size); ut_ad(n_chunks_new == n_chunks); ut_ad(UT_LIST_GET_LEN(withdraw) == 0); @@ -1673,7 +1671,7 @@ inline void buf_pool_t::resize() curr_size = n_chunks_new * chunks->size; mysql_mutex_unlock(&mutex); - if (curr_size < old_size) { + if (is_shrinking()) { /* set withdraw target */ size_t w = 0; @@ -1694,7 +1692,7 @@ inline void buf_pool_t::resize() withdraw_retry: /* wait for the number of blocks fit to the new size (if needed)*/ - bool should_retry_withdraw = curr_size < old_size + bool should_retry_withdraw = is_shrinking() && withdraw_blocks(); if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { @@ -1777,7 +1775,7 @@ withdraw_retry: ULINTPF " chunks to " ULINTPF " chunks.", n_chunks, n_chunks_new); - if (n_chunks_new < n_chunks) { + if (is_shrinking()) { /* delete chunks */ chunk_t* chunk = chunks + n_chunks_new; const chunk_t* const echunk = chunks + n_chunks; @@ -1841,8 +1839,7 @@ withdraw_retry: goto calc_buf_pool_size; } - ulint n_chunks_copy = ut_min(n_chunks_new, - n_chunks); + ulint n_chunks_copy = ut_min(n_chunks_new, n_chunks); memcpy(new_chunks, chunks, n_chunks_copy * sizeof *new_chunks); @@ -1909,7 +1906,6 @@ calc_buf_pool_size: /* set size */ ut_ad(UT_LIST_GET_LEN(withdraw) == 0); ulint s= curr_size; - old_size= s; s/= BUF_READ_AHEAD_PORTION; read_ahead_area= s >= READ_AHEAD_PAGES ? READ_AHEAD_PAGES @@ -3866,7 +3862,7 @@ void buf_pool_t::validate() mysql_mutex_unlock(&flush_list_mutex); - if (curr_size == old_size + if (n_chunks_new == n_chunks && n_lru + n_free > curr_size + n_zip) { ib::fatal() << "n_LRU " << n_lru << ", n_free " << n_free @@ -3876,7 +3872,7 @@ void buf_pool_t::validate() ut_ad(UT_LIST_GET_LEN(LRU) >= n_lru); - if (curr_size == old_size + if (n_chunks_new == n_chunks && UT_LIST_GET_LEN(free) != n_free) { ib::fatal() << "Free list len " diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 0fe9ce7a14b..1945cd04832 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1248,7 +1248,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) ulint free_limit= srv_LRU_scan_depth; mysql_mutex_assert_owner(&buf_pool.mutex); - if (buf_pool.withdraw_target && buf_pool.curr_size < buf_pool.old_size) + if (buf_pool.withdraw_target && buf_pool.is_shrinking()) free_limit+= buf_pool.withdraw_target - UT_LIST_GET_LEN(buf_pool.withdraw); const auto neighbors= UT_LIST_GET_LEN(buf_pool.LRU) < BUF_LRU_OLD_MIN_LEN diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 5469ac49b3a..e3f5de0697f 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -288,7 +288,7 @@ buf_block_t* buf_LRU_get_free_only() ut_a(!block->page.in_file()); UT_LIST_REMOVE(buf_pool.free, &block->page); - if (buf_pool.curr_size >= buf_pool.old_size + if (!buf_pool.is_shrinking() || UT_LIST_GET_LEN(buf_pool.withdraw) >= buf_pool.withdraw_target || !buf_pool.will_be_withdrawn(block->page)) { @@ -321,7 +321,7 @@ static void buf_LRU_check_size_of_non_data_objects() { mysql_mutex_assert_owner(&buf_pool.mutex); - if (recv_recovery_is_on() || buf_pool.curr_size != buf_pool.old_size) + if (recv_recovery_is_on() || buf_pool.n_chunks_new != buf_pool.n_chunks) return; const auto s= UT_LIST_GET_LEN(buf_pool.free) + UT_LIST_GET_LEN(buf_pool.LRU); @@ -1010,7 +1010,7 @@ buf_LRU_block_free_non_file_page( page_zip_set_size(&block->page.zip, 0); } - if (buf_pool.curr_size < buf_pool.old_size + if (buf_pool.is_shrinking() && UT_LIST_GET_LEN(buf_pool.withdraw) < buf_pool.withdraw_target && buf_pool.will_be_withdrawn(block->page)) { /* This should be withdrawn */ diff --git a/storage/innobase/dict/drop.cc b/storage/innobase/dict/drop.cc index 0093601f32f..0263c08118e 100644 --- a/storage/innobase/dict/drop.cc +++ b/storage/innobase/dict/drop.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2021, MariaDB Corporation. +Copyright (c) 2021, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -152,7 +152,7 @@ dberr_t trx_t::drop_table(const dict_table_t &table) ut_ad(table.n_lock_x_or_s == 1); ut_ad(UT_LIST_GET_LEN(table.locks) >= 1); #ifdef UNIV_DEBUG - bool found_x; + bool found_x= false; for (lock_t *lock= UT_LIST_GET_FIRST(table.locks); lock; lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) { diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 2039b45498a..c7004e0c8e8 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -224,18 +224,6 @@ fts_add_doc_by_id( /*==============*/ fts_trx_table_t*ftt, /*!< in: FTS trx table */ doc_id_t doc_id); /*!< in: doc id */ -/******************************************************************//** -Update the last document id. This function could create a new -transaction to update the last document id. -@return DB_SUCCESS if OK */ -static -dberr_t -fts_update_sync_doc_id( -/*===================*/ - const dict_table_t* table, /*!< in: table */ - doc_id_t doc_id, /*!< in: last document id */ - trx_t* trx) /*!< in: update trx, or NULL */ - MY_ATTRIBUTE((nonnull(1))); /** Tokenize a document. @param[in,out] doc document to tokenize @@ -2484,27 +2472,6 @@ fts_get_max_cache_size( #endif /*********************************************************************//** -Update the next and last Doc ID in the CONFIG table to be the input -"doc_id" value (+ 1). We would do so after each FTS index build or -table truncate */ -void -fts_update_next_doc_id( -/*===================*/ - trx_t* trx, /*!< in/out: transaction */ - const dict_table_t* table, /*!< in: table */ - doc_id_t doc_id) /*!< in: DOC ID to set */ -{ - table->fts->cache->synced_doc_id = doc_id; - table->fts->cache->next_doc_id = doc_id + 1; - - table->fts->cache->first_doc_id = table->fts->cache->next_doc_id; - - fts_update_sync_doc_id( - table, table->fts->cache->synced_doc_id, trx); - -} - -/*********************************************************************//** Get the next available document id. @return DB_SUCCESS if OK */ dberr_t @@ -2662,17 +2629,17 @@ func_exit: return(error); } -/*********************************************************************//** -Update the last document id. This function could create a new +/** Update the last document id. This function could create a new transaction to update the last document id. -@return DB_SUCCESS if OK */ -static +@param table table to be updated +@param doc_id last document id +@param trx update trx or null +@retval DB_SUCCESS if OK */ dberr_t fts_update_sync_doc_id( -/*===================*/ - const dict_table_t* table, /*!< in: table */ - doc_id_t doc_id, /*!< in: last document id */ - trx_t* trx) /*!< in: update trx, or NULL */ + const dict_table_t* table, + doc_id_t doc_id, + trx_t* trx) { byte id[FTS_MAX_ID_LEN]; pars_info_t* info; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a2ea8d50154..a36fe4a1897 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2752,44 +2752,6 @@ overflow: return(~(ulonglong) 0); } -/*******************************************************************//** -Reset the auto-increment counter to the given value, i.e. the next row -inserted will get the given value. This is called e.g. after TRUNCATE -is emulated by doing a 'DELETE FROM t'. HA_ERR_WRONG_COMMAND is -returned by storage engines that don't support this operation. -@return 0 or error code */ -int ha_innobase::reset_auto_increment(ulonglong value) -{ - DBUG_ENTER("ha_innobase::reset_auto_increment"); - - dberr_t error; - - update_thd(ha_thd()); - - error = row_lock_table_autoinc_for_mysql(m_prebuilt); - - if (error != DB_SUCCESS) { -err_exit: - DBUG_RETURN(convert_error_code_to_mysql( - error, m_prebuilt->table->flags, m_user_thd)); - } - - /* The next value can never be 0. */ - if (value == 0) { - value = 1; - } - - error = innobase_lock_autoinc(); - if (error != DB_SUCCESS) { - goto err_exit; - } - - dict_table_autoinc_initialize(m_prebuilt->table, value); - m_prebuilt->table->autoinc_mutex.wr_unlock(); - - DBUG_RETURN(0); -} - /*********************************************************************//** Initializes some fields in an InnoDB transaction object. */ static @@ -8726,16 +8688,6 @@ ha_innobase::delete_row( error, m_prebuilt->table->flags, m_user_thd)); } -/** Delete all rows from the table. -@return error number or 0 */ - -int -ha_innobase::delete_all_rows() -{ - DBUG_ENTER("ha_innobase::delete_all_rows"); - DBUG_RETURN(HA_ERR_WRONG_COMMAND); -} - /**********************************************************************//** Removes a new lock set on a row, if it was not read optimistically. This can be called after a row has been read in the processing of an UPDATE or a DELETE diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 4185f7a68cd..08501859ec9 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -109,8 +109,6 @@ public: double read_time(uint index, uint ranges, ha_rows rows) override; - int delete_all_rows() override; - int write_row(const uchar * buf) override; int update_row(const uchar * old_data, const uchar * new_data) override; @@ -244,7 +242,6 @@ public: ulonglong nb_desired_values, ulonglong* first_value, ulonglong* nb_reserved_values) override; - int reset_auto_increment(ulonglong value) override; bool get_error_message(int error, String *buf) override; diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index d584bab9263..e2b226b9e5c 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1344,7 +1344,7 @@ public: { ut_ad(is_initialised()); size_t size= 0; - for (auto j= n_chunks; j--; ) + for (auto j= ut_min(n_chunks_new, n_chunks); j--; ) size+= chunks[j].size; return size; } @@ -1354,7 +1354,7 @@ public: @return whether the frame will be withdrawn */ bool will_be_withdrawn(const byte *ptr) const { - ut_ad(curr_size < old_size); + ut_ad(n_chunks_new < n_chunks); #ifdef SAFE_MUTEX if (resize_in_progress()) mysql_mutex_assert_owner(&mutex); @@ -1374,7 +1374,7 @@ public: @return whether the frame will be withdrawn */ bool will_be_withdrawn(const buf_page_t &bpage) const { - ut_ad(curr_size < old_size); + ut_ad(n_chunks_new < n_chunks); #ifdef SAFE_MUTEX if (resize_in_progress()) mysql_mutex_assert_owner(&mutex); @@ -1531,11 +1531,18 @@ public: inline void watch_remove(buf_page_t *watch, hash_chain &chain); /** @return whether less than 1/4 of the buffer pool is available */ + TPOOL_SUPPRESS_TSAN bool running_out() const { return !recv_recovery_is_on() && - UNIV_UNLIKELY(UT_LIST_GET_LEN(free) + UT_LIST_GET_LEN(LRU) < - std::min(curr_size, old_size) / 4); + UT_LIST_GET_LEN(free) + UT_LIST_GET_LEN(LRU) < + n_chunks_new / 4 * chunks->size; + } + + /** @return whether the buffer pool is shrinking */ + inline bool is_shrinking() const + { + return n_chunks_new < n_chunks; } #ifdef UNIV_DEBUG @@ -1594,15 +1601,15 @@ public: ut_allocator<unsigned char> allocator; /*!< Allocator used for allocating memory for the the "chunks" member. */ - volatile ulint n_chunks; /*!< number of buffer pool chunks */ - volatile ulint n_chunks_new; /*!< new number of buffer pool chunks */ + ulint n_chunks; /*!< number of buffer pool chunks */ + ulint n_chunks_new; /*!< new number of buffer pool chunks. + both n_chunks{,new} are protected under + mutex */ chunk_t* chunks; /*!< buffer pool chunks */ chunk_t* chunks_old; /*!< old buffer pool chunks to be freed after resizing buffer pool */ /** current pool size in pages */ Atomic_counter<ulint> curr_size; - /** previous pool size in pages */ - Atomic_counter<ulint> old_size; /** read-ahead request size in pages */ Atomic_counter<uint32_t> read_ahead_area; diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index b83a385938b..774221dd208 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -398,17 +398,6 @@ fts_get_next_doc_id( /*================*/ const dict_table_t* table, /*!< in: table */ doc_id_t* doc_id);/*!< out: new document id */ -/*********************************************************************//** -Update the next and last Doc ID in the CONFIG table to be the input -"doc_id" value (+ 1). We would do so after each FTS index build or -table truncate */ -void -fts_update_next_doc_id( -/*===================*/ - trx_t* trx, /*!< in/out: transaction */ - const dict_table_t* table, /*!< in: table */ - doc_id_t doc_id) /*!< in: DOC ID to set */ - MY_ATTRIBUTE((nonnull(2))); /******************************************************************//** Create a new fts_doc_ids_t. @@ -950,6 +939,18 @@ bool fts_check_aux_table(const char *name, table_id_t *table_id, index_id_t *index_id); +/** Update the last document id. This function could create a new +transaction to update the last document id. +@param table table to be updated +@param doc_id last document id +@param trx update trx or null +@retval DB_SUCCESS if OK */ +dberr_t +fts_update_sync_doc_id(const dict_table_t *table, + doc_id_t doc_id, + trx_t *trx) + MY_ATTRIBUTE((nonnull(1))); + /** Sync the table during commit phase @param[in] table table to be synced */ void fts_sync_during_ddl(dict_table_t* table); diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index a732c17f767..6eb5bb3f183 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -94,29 +94,6 @@ do {\ }\ } while (0) -/*******************************************************************//** -Inserts a struct to the head of hash table. */ - -#define HASH_PREPEND(TYPE, NAME, TABLE, FOLD, DATA) \ -do { \ - hash_cell_t* cell3333; \ - TYPE* struct3333; \ - \ - (DATA)->NAME = NULL; \ - \ - cell3333 = &(TABLE)->array[(TABLE)->calc_hash(FOLD)]; \ - \ - if (cell3333->node == NULL) { \ - cell3333->node = DATA; \ - DATA->NAME = NULL; \ - } else { \ - struct3333 = (TYPE*) cell3333->node; \ - \ - DATA->NAME = struct3333; \ - \ - cell3333->node = DATA; \ - } \ -} while (0) #ifdef UNIV_HASH_DEBUG # define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1) # define HASH_INVALIDATE(DATA, NAME) *(void**) (&DATA->NAME) = (void*) -1 diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index b7ff8b61752..28d75517d45 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -1175,10 +1175,6 @@ without checking for deadlocks or conflicts. @param[in] index the index tree @param[in,out] trx transaction @param[in] holds_trx_mutex whether the caller holds trx->mutex -@param[in] insert_before_waiting if true, inserts new B-tree record lock -just after the last non-waiting lock of the current transaction which is -located before the first waiting for the current transaction lock, otherwise -the lock is inserted at the end of the queue @return created lock */ lock_t* lock_rec_create_low( @@ -1189,8 +1185,7 @@ lock_rec_create_low( ulint heap_no, dict_index_t* index, trx_t* trx, - bool holds_trx_mutex, - bool insert_before_waiting = false); + bool holds_trx_mutex); /** Enqueue a waiting request for a lock which cannot be granted immediately. Check for deadlocks. diff --git a/storage/innobase/include/lock0lock.inl b/storage/innobase/include/lock0lock.inl index 7d08cbb930c..ca64587628a 100644 --- a/storage/innobase/include/lock0lock.inl +++ b/storage/innobase/include/lock0lock.inl @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, MariaDB Corporation. +Copyright (c) 2017, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index 4e469c6598c..b0a5f7aaf3b 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2021, MariaDB Corporation. +Copyright (c) 2015, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/include/lock0priv.inl b/storage/innobase/include/lock0priv.inl index 21e7c7c95dc..3b4ebcc835b 100644 --- a/storage/innobase/include/lock0priv.inl +++ b/storage/innobase/include/lock0priv.inl @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2021, MariaDB Corporation. +Copyright (c) 2018, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 24bafa61337..64b0923229b 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2021, MariaDB Corporation. +Copyright (c) 2015, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 5551c85db0b..fa1ea357fe6 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1010,37 +1010,17 @@ LOCK_INSERT_INTENTION @param[in] id page identifier @param[in] heap_no heap number of the record @param[in] trx our transaction -@param[out] was_ignored true if conflicting locks waiting for the current -transaction were ignored @return conflicting lock and the flag which indicated if conflicting locks which wait for the current transaction were ignored */ static lock_t *lock_rec_other_has_conflicting(unsigned mode, const hash_cell_t &cell, const page_id_t id, - ulint heap_no, const trx_t *trx, - bool *was_ignored= nullptr) + ulint heap_no, const trx_t *trx) { bool is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM); for (lock_t* lock = lock_sys_t::get_first(cell, id, heap_no); lock; lock = lock_rec_get_next(heap_no, lock)) { - /* There is no need to lock lock_sys.wait_mutex to check - trx->lock.wait_trx here because the current function is - executed under the cell latch, and trx->lock.wait_trx - transaction can change wait_trx field only under the cell - latch, wait_trx trx_t object can not be deinitialized before - releasing all its locks, and during releasing the locks the - cell latch will also be requested. So while the cell latch is - held, lock->trx->lock.wait_trx can't be changed. There also - can't be lock loops for one record, because all waiting locks - of the record will always wait for the same lock of the record - in a cell array, and check for conflicting lock will always - start with the first lock for the heap_no, and go ahead with - the same order(the order of the locks in the cell array) */ - if (lock->is_waiting() && lock->trx->lock.wait_trx == trx) { - if (was_ignored) *was_ignored= true; - continue; - } if (lock_rec_has_to_wait(true, trx, mode, lock, is_supremum)) { return(lock); } @@ -1166,10 +1146,6 @@ without checking for deadlocks or conflicts. @param[in] index the index tree @param[in,out] trx transaction @param[in] holds_trx_mutex whether the caller holds trx->mutex -@param[in] insert_before_waiting if true, inserts new B-tree record lock -just after the last non-waiting lock of the current transaction which is -located before the first waiting for the current transaction lock, otherwise -the lock is inserted at the end of the queue @return created lock */ lock_t* lock_rec_create_low( @@ -1180,8 +1156,7 @@ lock_rec_create_low( ulint heap_no, dict_index_t* index, trx_t* trx, - bool holds_trx_mutex, - bool insert_before_waiting) + bool holds_trx_mutex) { lock_t* lock; ulint n_bytes; @@ -1256,36 +1231,7 @@ lock_rec_create_low( ut_ad(index->table->get_ref_count() || !index->table->can_be_evicted); const auto lock_hash = &lock_sys.hash_get(type_mode); - hash_cell_t& cell = *lock_hash->cell_get(page_id.fold()); - - if (insert_before_waiting - && !(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE))) { - /* Try to insert the lock just after the last non-waiting - lock of the current transaction which immediately - precedes the first waiting lock request. */ - - lock_t* last_non_waiting = nullptr; - - for (lock_t* l = lock_sys_t::get_first(cell, page_id, heap_no); - l; l = lock_rec_get_next(heap_no, l)) { - if (l->is_waiting() && l->trx->lock.wait_trx == trx) { - break; - } - if (l->trx == trx) { - last_non_waiting = l; - } - } - - if (!last_non_waiting) { - goto append_last; - } - - cell.insert_after(*last_non_waiting, *lock, &lock_t::hash); - } - else { -append_last: - cell.append(*lock, &lock_t::hash); - } + lock_hash->cell_get(page_id.fold())->append(*lock, &lock_t::hash); if (type_mode & LOCK_WAIT) { if (trx->lock.wait_trx) { @@ -1311,7 +1257,6 @@ append_last: /** Enqueue a waiting request for a lock which cannot be granted immediately. Check for deadlocks. -@param[in] c_lock conflicting lock @param[in] type_mode the requested lock mode (LOCK_S or LOCK_X) possibly ORed with LOCK_GAP or LOCK_REC_NOT_GAP, ORed with @@ -1417,15 +1362,12 @@ which does NOT check for deadlocks or lock compatibility! @param[in] heap_no heap number of the record @param[in] index index of record @param[in,out] trx transaction -@param[in] caller_owns_trx_mutex TRUE if caller owns the transaction mutex -@param[in] insert_before_waiting true=insert B-tree record lock right -before a waiting lock request; false=insert the lock at the end of the queue */ +@param[in] caller_owns_trx_mutex TRUE if caller owns the transaction mutex */ TRANSACTIONAL_TARGET static void lock_rec_add_to_queue(unsigned type_mode, hash_cell_t &cell, const page_id_t id, const page_t *page, ulint heap_no, dict_index_t *index, - trx_t *trx, bool caller_owns_trx_mutex, - bool insert_before_waiting= false) + trx_t *trx, bool caller_owns_trx_mutex) { ut_d(lock_sys.hash_get(type_mode).assert_locked(id)); ut_ad(xtest() || caller_owns_trx_mutex == trx->mutex_is_owner()); @@ -1520,7 +1462,7 @@ create: lock_rec_create_low(nullptr, type_mode, id, page, heap_no, index, trx, - caller_owns_trx_mutex, insert_before_waiting); + caller_owns_trx_mutex); } /*********************************************************************//** @@ -1587,10 +1529,8 @@ lock_rec_lock( /* Do nothing if the trx already has a strong enough lock on rec */ if (!lock_rec_has_expl(mode, g.cell(), id, heap_no, trx)) { - bool was_ignored = false; if (lock_t *c_lock= lock_rec_other_has_conflicting(mode, g.cell(), id, - heap_no, trx, - &was_ignored)) + heap_no, trx)) /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not @@ -1603,7 +1543,7 @@ lock_rec_lock( { /* Set the requested lock on the record. */ lock_rec_add_to_queue(mode, g.cell(), id, block->page.frame, heap_no, - index, trx, true, was_ignored); + index, trx, true); err= DB_SUCCESS_LOCKED_REC; } } @@ -4707,7 +4647,7 @@ func_exit: wsrep_report_bf_lock_wait(impl_trx->mysql_thd, impl_trx->id); wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id); - if (!lock_rec_has_expl(LOCK_S | LOCK_REC_NOT_GAP, + if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, cell, id, heap_no, impl_trx)) { ib::info() << "WSREP impl BF lock conflict"; @@ -4716,22 +4656,8 @@ func_exit: #endif /* WITH_WSREP */ { ut_ad(other_lock->is_waiting()); - /* After MDEV-27025 fix the following case is - possible: - 1. trx 1 acquires S-lock; - 2. trx 2 creates X-lock waiting for trx 1; - 3. trx 1 creates implicit lock, as - lock_rec_other_has_conflicting() returns no - conflicting trx 2 X-lock, the explicit lock - will not be created; - 4. trx 3 creates waiting X-lock, - it will wait for S-lock of trx 1. - That is why we relaxing the condition here and - check only for S-lock. - */ - ut_ad(lock_rec_has_expl(LOCK_S - | LOCK_REC_NOT_GAP, - cell, id, heap_no, + ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, + cell, id, heap_no, impl_trx)); } } @@ -5127,7 +5053,7 @@ lock_rec_convert_impl_to_expl_for_trx( !lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, heap_no, trx)) lock_rec_add_to_queue(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, - page_align(rec), heap_no, index, trx, true, true); + page_align(rec), heap_no, index, trx, true); } trx->mutex_unlock(); diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc index e924d46bd3f..5a12d97411f 100644 --- a/storage/innobase/lock/lock0prdt.cc +++ b/storage/innobase/lock/lock0prdt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2021, MariaDB Corporation. +Copyright (c) 2018, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index da8f62177cb..785b7b6070d 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -3013,7 +3013,21 @@ wait_again: err = fts_sync_table(const_cast<dict_table_t*>(new_table)); if (err == DB_SUCCESS) { - fts_update_next_doc_id(NULL, new_table, max_doc_id); + new_table->fts->cache->synced_doc_id = max_doc_id; + + /* Update the max value as next FTS_DOC_ID */ + if (max_doc_id >= new_table->fts->cache->next_doc_id) { + new_table->fts->cache->next_doc_id = + max_doc_id + 1; + } + + new_table->fts->cache->first_doc_id = + new_table->fts->cache->next_doc_id; + + err= fts_update_sync_doc_id( + new_table, + new_table->fts->cache->synced_doc_id, + NULL); } } |