mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 19:41:44 +02:00

Statements that intend to modify data have to acquire protection
against ongoing backup. Prior to backup locks, protection against
FTWRL was acquired in form of 2 shared metadata locks of GLOBAL
(global read lock) and COMMIT namespaces. These two namespaces
were separate entities, they didn't share data structures and
locking primitives. And thus they were separate contention
points.
With backup locks, introduced by 7a9dfdd
, these namespaces were
combined into a single BACKUP namespace. It became a single
contention point, which doubled load on BACKUP namespace data
structures and locking primitives compared to GLOBAL and COMMIT
namespaces. In other words system throughput has halved.
MDL fast lanes solve this problem by allowing multiple contention
points for single MDL_lock. Fast lane is scalable multi-instance
registry for leightweight locks. Internally it is just a list of
granted tickets, close counter and a mutex.
Number of fast lanes (or contention points) is defined by the
metadata_locks_instances system variable. Value of 1 disables fast
lanes and lock requests are served by conventional MDL_lock data
structures.
Since fast lanes allow arbitrary number of contention points, they
outperform pre-backup locks GLOBAL and COMMIT.
Fast lanes are enabled only for BACKUP namespace. Support for other
namespaces is to be implemented separately.
Lock types are divided in 2 categories: lightweight and heavyweight.
Lightweight lock types represent DML: MDL_BACKUP_DML,
MDL_BACKUP_TRANS_DML, MDL_BACKUP_SYS_DML, MDL_BACKUP_DDL,
MDL_BACKUP_ALTER_COPY, MDL_BACKUP_COMMIT. They are fully compatible
with each other. Normally served by corresponding fast lane, which is
determined by thread_id % metadata_locks_instances.
Heavyweight lock types represent ongoing backup: MDL_BACKUP_START,
MDL_BACKUP_FLUSH, MDL_BACKUP_WAIT_FLUSH, MDL_BACKUP_WAIT_DDL,
MDL_BACKUP_WAIT_COMMIT, MDL_BACKUP_FTWRL1, MDL_BACKUP_FTWRL2,
MDL_BACKUP_BLOCK_DDL. These locks are always served by conventional
MDL_lock data structures. Whenever such lock is requested, fast
lanes are closed and all tickets registered in fast lanes are
moved to conventional MDL_lock data structures. Until such locks
are released or aborted, lightweight lock requests are served by
conventional MDL_lock data structures.
Strictly speaking moving tickets from fast lanes to conventional
MDL_lock data structures is not required. But it allows to reduce
complexity and keep intact methods like: MDL_lock::visit_subgraph(),
MDL_lock::notify_conflicting_locks(), MDL_lock::reschedule_waiters(),
MDL_lock::can_grant_lock().
It is not even required to register tickets in fast lanes. They
can be implemented basing on an atomic variable that holds two
counters: granted lightweight locks and granted/waiting heavyweight
locks. Similarly to MySQL solution, which roughly speaking has
"single atomic fast lane". However it appears to be it won't bring
any better performance, while code complexity is going to be much
higher.
144 lines
4.6 KiB
Text
144 lines
4.6 KiB
Text
#
|
|
# MDEV-12882 - Assertion `mdl_ticket->m_type == MDL_SHARED_UPGRADABLE ||
|
|
# mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
|
|
# mdl_ticket->m_type == MDL_SHARED_NO_READ_WRITE ||
|
|
# mdl_ticket->m_type == MDL_SHARED_READ'
|
|
# failed in MDL_context::upgrade_shared_lock
|
|
#
|
|
CREATE TABLE t1(a INT) ENGINE=InnoDB;
|
|
CREATE TABLE t3(a INT) ENGINE=myisam;
|
|
LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_TRANS_DML Backup lock
|
|
MDL_SHARED_NO_READ_WRITE Table metadata lock test t1
|
|
UNLOCK TABLES;
|
|
LOCK TABLES t1 AS t2 READ, t1 WRITE CONCURRENT;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_TRANS_DML Backup lock
|
|
MDL_SHARED_WRITE Table metadata lock test t1
|
|
MDL_SHARED_READ_ONLY Table metadata lock test t1
|
|
UNLOCK TABLES;
|
|
LOCK TABLES t1 WRITE CONCURRENT, t3 WRITE;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_DDL Backup lock
|
|
MDL_BACKUP_DML Backup lock
|
|
MDL_INTENTION_EXCLUSIVE Schema metadata lock test
|
|
MDL_SHARED_NO_READ_WRITE Table metadata lock test t3
|
|
MDL_SHARED_WRITE Table metadata lock test t1
|
|
UNLOCK TABLES;
|
|
LOCK TABLES t3 WRITE, t1 WRITE CONCURRENT;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_DDL Backup lock
|
|
MDL_BACKUP_DML Backup lock
|
|
MDL_INTENTION_EXCLUSIVE Schema metadata lock test
|
|
MDL_SHARED_NO_READ_WRITE Table metadata lock test t3
|
|
MDL_SHARED_WRITE Table metadata lock test t1
|
|
UNLOCK TABLES;
|
|
LOCK TABLES t1 WRITE, mysql.user WRITE;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_DDL Backup lock
|
|
MDL_SHARED_NO_READ_WRITE Table metadata lock mysql user
|
|
MDL_SHARED_NO_READ_WRITE Table metadata lock test t1
|
|
MDL_INTENTION_EXCLUSIVE Schema metadata lock mysql
|
|
MDL_SHARED_NO_READ_WRITE Table metadata lock mysql global_priv
|
|
MDL_INTENTION_EXCLUSIVE Schema metadata lock test
|
|
UNLOCK TABLES;
|
|
LOCK TABLES mysql.general_log WRITE;
|
|
ERROR HY000: You can't use locks with log tables
|
|
LOCK TABLES t1 WRITE,information_schema.tables READ;
|
|
UNLOCK TABLES;
|
|
DROP TABLE t1,t3;
|
|
#
|
|
# Check MDL locks taken for different kind of tables by open
|
|
#
|
|
CREATE TABLE t1(a INT) stats_persistent=0, ENGINE=InnoDB;
|
|
CREATE TABLE t3(a INT) ENGINE=myisam;
|
|
connect purge_control,localhost,root,,;
|
|
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
|
connect locker,localhost,root,,;
|
|
connection default;
|
|
FLUSH TABLES WITH READ LOCK;
|
|
connection locker;
|
|
insert into t1 values (1);
|
|
connection default;
|
|
connection default;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_FTWRL2 Backup lock
|
|
MDL_SHARED_WRITE Table metadata lock test t1
|
|
unlock tables;
|
|
connection locker;
|
|
unlock tables;
|
|
connection default;
|
|
FLUSH TABLES WITH READ LOCK;
|
|
connection locker;
|
|
insert into t3 values (2);
|
|
connection default;
|
|
connection default;
|
|
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
|
|
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
|
|
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
|
|
MDL_BACKUP_FTWRL2 Backup lock
|
|
MDL_SHARED_WRITE Table metadata lock test t3
|
|
unlock tables;
|
|
connection locker;
|
|
unlock tables;
|
|
disconnect purge_control;
|
|
connection default;
|
|
disconnect locker;
|
|
DROP TABLE t1,t3;
|
|
#
|
|
# MDEV-28820 MyISAM wrong server status flags
|
|
#
|
|
create table t1 (a int);
|
|
set autocommit=0;
|
|
select @@in_transaction;
|
|
@@in_transaction
|
|
0
|
|
select * from t1;
|
|
a
|
|
select @@in_transaction;
|
|
@@in_transaction
|
|
0
|
|
connect foo,localhost,root;
|
|
drop table t1;
|
|
connection default;
|
|
set autocommit=1;
|
|
create table t1 (a int);
|
|
create table t2 (b int) engine=innodb;
|
|
set autocommit=0;
|
|
select @@in_transaction;
|
|
@@in_transaction
|
|
0
|
|
select * from t2;
|
|
b
|
|
select @@in_transaction;
|
|
@@in_transaction
|
|
1
|
|
select * from t1;
|
|
a
|
|
connection foo;
|
|
drop table t1;
|
|
connection default;
|
|
select * from t1;
|
|
a
|
|
commit;
|
|
connection foo;
|
|
disconnect foo;
|
|
connection default;
|
|
set autocommit=default;
|
|
drop table t2;
|
|
#
|
|
# End of 10.4 tests
|
|
#
|