mirror of
https://github.com/MariaDB/server.git
synced 2025-09-11 05:52:26 +03:00
This is a complete rewrite of DROP TABLE, also as part of other DDL, such as ALTER TABLE, CREATE TABLE...SELECT, TRUNCATE TABLE. The background DROP TABLE queue hack is removed. If a transaction needs to drop and create a table by the same name (like TRUNCATE TABLE does), it must first rename the table to an internal #sql-ib name. No committed version of the data dictionary will include any #sql-ib tables, because whenever a transaction renames a table to a #sql-ib name, it will also drop that table. Either the rename will be rolled back, or the drop will be committed. Data files will be unlinked after the transaction has been committed and a FILE_RENAME record has been durably written. The file will actually be deleted when the detached file handle returned by fil_delete_tablespace() will be closed, after the latches have been released. It is possible that a purge of the delete of the SYS_INDEXES record for the clustered index will execute fil_delete_tablespace() concurrently with the DDL transaction. In that case, the thread that arrives later will wait for the other thread to finish. HTON_TRUNCATE_REQUIRES_EXCLUSIVE_USE: A new handler flag. ha_innobase::truncate() now requires that all other references to the table be released in advance. This was implemented by Monty. ha_innobase::delete_table(): If CREATE TABLE..SELECT is detected, we will "hijack" the current transaction, drop the table in the current transaction and commit the current transaction. This essentially fixes MDEV-21602. There is a FIXME comment about making the check less failure-prone. ha_innobase::truncate(), ha_innobase::delete_table(): Implement a fast path for temporary tables. We will no longer allow temporary tables to use the adaptive hash index. dict_table_t::mdl_name: The original table name for the purpose of acquiring MDL in purge, to prevent a race condition between a DDL transaction that is dropping a table, and purge processing undo log records of DML that had executed before the DDL operation. For #sql-backup- tables during ALTER TABLE...ALGORITHM=COPY, the dict_table_t::mdl_name will differ from dict_table_t::name. dict_table_t::parse_name(): Use mdl_name instead of name. dict_table_rename_in_cache(): Update mdl_name. For the internal FTS_ tables of FULLTEXT INDEX, purge would acquire MDL on the FTS_ table name, but not on the main table, and therefore it would be able to run concurrently with a DDL transaction that is dropping the table. Previously, the DROP TABLE queue hack prevented a race between purge and DDL. For now, we introduce purge_sys.stop_FTS() to prevent purge from opening any table, while a DDL transaction that may drop FTS_ tables is in progress. The function fts_lock_table(), which will be invoked before the dictionary is locked, will wait for purge to release any table handles. trx_t::drop_table_statistics(): Drop statistics for the table. This replaces dict_stats_drop_index(). We will drop or rename persistent statistics atomically as part of DDL transactions. On lock conflict for dropping statistics, we will fail instantly with DB_LOCK_WAIT_TIMEOUT, because we will be holding the exclusive data dictionary latch. trx_t::commit_cleanup(): Separated from trx_t::commit_in_memory(). Relax an assertion around fts_commit() and allow DB_LOCK_WAIT_TIMEOUT in addition to DB_DUPLICATE_KEY. The call to fts_commit() is entirely misplaced here and may obviously break the consistency of transactions that affect FULLTEXT INDEX. It needs to be fixed separately. dict_table_t::n_foreign_key_checks_running: Remove (MDEV-21175). The counter was a work-around for missing meta-data locking (MDL) on the SQL layer, and not really needed in MariaDB. ER_TABLE_IN_FK_CHECK: Replaced with ER_UNUSED_28. HA_ERR_TABLE_IN_FK_CHECK: Remove. row_ins_check_foreign_constraints(): Do not acquire dict_sys.latch either. The SQL-layer MDL will protect us. This was reviewed by Thirunarayanan Balathandayuthapani and tested by Matthias Leich.
257 lines
8.1 KiB
Plaintext
257 lines
8.1 KiB
Plaintext
# Crash recovery tests for FULLTEXT INDEX.
|
|
# Note: These tests used to be part of a larger test, innodb_fts_misc_debug
|
|
# or innodb_fts.misc_debug. The part of the test that actually needs debug
|
|
# instrumentation been moved to innodb_fts.misc_debug.
|
|
|
|
--source include/have_innodb.inc
|
|
# The embedded server tests do not support restarting.
|
|
--source include/not_embedded.inc
|
|
--source include/maybe_debug.inc
|
|
if ($have_debug) { source include/have_debug_sync.inc; }
|
|
|
|
FLUSH TABLES;
|
|
# Following are test for crash recovery on FTS index, the first scenario
|
|
# is for bug Bug #14586855 INNODB: FAILING ASSERTION: (DICT_INDEX_GET_N_UNIQUE(
|
|
# PLAN->INDEX) <= PLAN->N_EXAC
|
|
|
|
# Scenario 1: Hidden FTS_DOC_ID column, and FTS index dropped
|
|
# Create FTS table
|
|
CREATE TABLE articles (
|
|
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
|
title VARCHAR(200),
|
|
body TEXT,
|
|
FULLTEXT (title,body)
|
|
) ENGINE=InnoDB;
|
|
|
|
# Drop the FTS index before more insertion. The FTS_DOC_ID should
|
|
# be kept
|
|
DROP INDEX title ON articles;
|
|
|
|
# Insert six rows
|
|
INSERT INTO articles (title,body) VALUES
|
|
('MySQL Tutorial','DBMS stands for DataBase ...') ,
|
|
('How To Use MySQL Well','After you went through a ...'),
|
|
('Optimizing MySQL','In this tutorial we will show ...'),
|
|
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
|
|
('MySQL vs. YourSQL','In the following database comparison ...'),
|
|
('MySQL Security','When configured properly, MySQL ...');
|
|
|
|
BEGIN;
|
|
INSERT INTO articles (title,body) VALUES
|
|
('MySQL Tutorial','DBMS stands for DataBase ...');
|
|
|
|
--echo # Make durable the AUTO_INCREMENT in the above incomplete transaction.
|
|
--connect(ddl1, localhost, root,,)
|
|
CREATE TABLE t1(a TEXT,b TEXT,FULLTEXT INDEX(a)) ENGINE=InnoDB;
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL 1 WAIT_FOR ever';
|
|
--enable_query_log
|
|
}
|
|
send ALTER TABLE t1 ADD FULLTEXT INDEX(b);
|
|
--connection default
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_SYNC='now WAIT_FOR 1';
|
|
--enable_query_log
|
|
}
|
|
|
|
--connect(ddl2, localhost, root,,)
|
|
CREATE TABLE t2(a TEXT,b TEXT,FULLTEXT INDEX(a)) ENGINE=InnoDB;
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL 2 WAIT_FOR ever';
|
|
--enable_query_log
|
|
}
|
|
send ALTER TABLE t2 DROP INDEX a, ADD FULLTEXT INDEX(b), FORCE;
|
|
--connection default
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_SYNC='now WAIT_FOR 2';
|
|
--enable_query_log
|
|
}
|
|
|
|
--connect(ddl3, localhost, root,,)
|
|
CREATE TABLE t3(a TEXT,b TEXT,FULLTEXT INDEX(a)) ENGINE=InnoDB;
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_SYNC='alter_table_before_rename_result_table SIGNAL 3 WAIT_FOR ever';
|
|
--enable_query_log
|
|
}
|
|
send ALTER TABLE t3 DROP INDEX a, ADD FULLTEXT INDEX(b), ALGORITHM=COPY;
|
|
|
|
--connection default
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_SYNC='now WAIT_FOR 3';
|
|
--enable_query_log
|
|
}
|
|
|
|
let $shutdown_timeout=0;
|
|
--source include/restart_mysqld.inc
|
|
|
|
disconnect ddl1;
|
|
disconnect ddl2;
|
|
disconnect ddl3;
|
|
|
|
# Ensure that the history list length will actually be decremented by purge.
|
|
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
|
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
|
|
# Wait for purge, so that any #sql-ib.ibd files from the previous kill
|
|
# will be deleted.
|
|
source ../../innodb/include/wait_all_purged.inc;
|
|
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
|
|
|
|
CHECK TABLE t1,t2,t3;
|
|
DROP TABLE t1,t2,t3;
|
|
|
|
# This insert will re-initialize the Doc ID counter, it should not crash
|
|
INSERT INTO articles (title,body) VALUES
|
|
('MySQL Tutorial','DBMS stands for DataBase ...');
|
|
|
|
# Recreate fulltext index to see if everything is OK
|
|
CREATE FULLTEXT INDEX idx ON articles (title,body);
|
|
|
|
# Should return 3 rows
|
|
SELECT * FROM articles
|
|
WHERE MATCH (title,body)
|
|
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
|
|
|
|
# Scenario 2: Hidden FTS_DOC_ID column, with FTS index
|
|
# Now let's do more insertion and test a crash with FTS on
|
|
INSERT INTO articles (title,body) VALUES
|
|
('MySQL Tutorial','DBMS stands for DataBase ...') ,
|
|
('How To Use MySQL Well','After you went through a ...'),
|
|
('Optimizing MySQL','In this tutorial we will show ...'),
|
|
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
|
|
('MySQL vs. YourSQL','In the following database comparison ...'),
|
|
('MySQL Security','When configured properly, MySQL ...');
|
|
|
|
connect(dml, localhost, root,,);
|
|
BEGIN;
|
|
|
|
INSERT INTO articles (title,body) VALUES
|
|
('MySQL Tutorial','DBMS stands for DataBase ...');
|
|
connection default;
|
|
|
|
--echo # Make durable the AUTO_INCREMENT in the above incomplete transaction.
|
|
--connect (flush_redo_log,localhost,root,,)
|
|
SET GLOBAL innodb_flush_log_at_trx_commit=1;
|
|
BEGIN;
|
|
DELETE FROM articles LIMIT 1;
|
|
ROLLBACK;
|
|
--disconnect flush_redo_log
|
|
--connection default
|
|
|
|
--source include/restart_mysqld.inc
|
|
|
|
disconnect dml;
|
|
|
|
# This insert will re-initialize the Doc ID counter, it should not crash
|
|
INSERT INTO articles (title,body) VALUES
|
|
('MySQL Tutorial','DBMS stands for DataBase ...');
|
|
|
|
# Should return 6 rows
|
|
SELECT * FROM articles
|
|
WHERE MATCH (title,body)
|
|
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
|
|
|
|
DROP TABLE articles;
|
|
|
|
# Scenario 3: explicit FTS_DOC_ID column with FTS index
|
|
# Now let's test user defined FTS_DOC_ID
|
|
|
|
CREATE TABLE articles (
|
|
id int PRIMARY KEY,
|
|
FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
|
|
title VARCHAR(200),
|
|
body TEXT
|
|
) ENGINE=InnoDB;
|
|
|
|
CREATE FULLTEXT INDEX idx1 on articles (title, body);
|
|
|
|
# Note the FTS_DOC_ID is not fully ordered with primary index
|
|
INSERT INTO articles VALUES
|
|
(1, 10, 'MySQL Tutorial','DBMS stands for DataBase ...') ,
|
|
(2, 1, 'How To Use MySQL Well','After you went through a ...'),
|
|
(3, 2, 'Optimizing MySQL','In this tutorial we will show ...'),
|
|
(4, 11, '1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
|
|
(5, 6, 'MySQL vs. YourSQL','In the following database comparison ...'),
|
|
(7, 4, 'MySQL Security','When configured properly, MySQL ...');
|
|
|
|
connect(dml, localhost, root,,);
|
|
BEGIN;
|
|
|
|
# Below we do not depend on the durability of the AUTO_INCREMENT sequence,
|
|
# so we can skip the above flush_redo_log trick.
|
|
INSERT INTO articles VALUES
|
|
(100, 200, 'MySQL Tutorial','DBMS stands for DataBase ...');
|
|
|
|
connect(dml2, localhost, root,,);
|
|
|
|
--echo #
|
|
--echo # MDEV-19073 FTS row mismatch after crash recovery
|
|
--echo #
|
|
|
|
CREATE TABLE mdev19073(id SERIAL, title VARCHAR(200), body TEXT,
|
|
FULLTEXT(title,body)) ENGINE=InnoDB;
|
|
INSERT INTO mdev19073 (title, body) VALUES
|
|
('MySQL Tutorial', 'DBMS stands for Database...');
|
|
CREATE FULLTEXT INDEX idx ON mdev19073(title, body);
|
|
CREATE TABLE mdev19073_2 LIKE mdev19073;
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET @saved_dbug = @@debug_dbug;
|
|
SET DEBUG_DBUG = '+d,fts_instrument_sync_debug';
|
|
--enable_query_log
|
|
}
|
|
INSERT INTO mdev19073_2 (title, body) VALUES
|
|
('MySQL Tutorial', 'DBMS stands for Database...');
|
|
if ($have_debug)
|
|
{
|
|
--disable_query_log
|
|
SET DEBUG_DBUG = @saved_dbug;
|
|
--enable_query_log
|
|
}
|
|
|
|
INSERT INTO mdev19073 (title, body) VALUES
|
|
('MariaDB Tutorial', 'DB means Database ...');
|
|
INSERT INTO mdev19073_2 (title, body) VALUES
|
|
('MariaDB Tutorial', 'DB means Database ...');
|
|
|
|
# Should return 2 rows
|
|
SELECT * FROM mdev19073 WHERE MATCH (title, body)
|
|
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
|
|
SELECT * FROM mdev19073_2 WHERE MATCH (title, body)
|
|
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
|
|
|
|
connection default;
|
|
--source include/restart_mysqld.inc
|
|
disconnect dml;
|
|
disconnect dml2;
|
|
|
|
# This would re-initialize the FTS index and do the re-tokenization
|
|
# of above records
|
|
INSERT INTO articles VALUES (8, 12, 'MySQL Tutorial','DBMS stands for DataBase ...');
|
|
|
|
SELECT * FROM articles WHERE MATCH (title, body)
|
|
AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE);
|
|
|
|
DROP TABLE articles;
|
|
|
|
# Should return 2 rows
|
|
SELECT * FROM mdev19073 WHERE MATCH (title, body)
|
|
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
|
|
SELECT * FROM mdev19073_2 WHERE MATCH (title, body)
|
|
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
|
|
DROP TABLE mdev19073, mdev19073_2;
|
|
|
|
SELECT * FROM information_schema.innodb_sys_tables WHERE name LIKE 'test/%';
|