为什么 'lock_type' of information_schema.INNODB_LOCKS 总是 RECORD?
Why does 'lock_type' of information_schema.INNODB_LOCKS always RECORD?
根据文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-table.html、
LOCK_TYPE of INFORMATION_SCHEMA INNODB_LOCKS Table should have 2
possible values: RECORD AND TABLE.
但是,我还没有看到那个字段是 "TABLE"。无论我尝试什么,它总是 "RECORD"。有没有人可以给我一个案例来实现 "TABLE"?
谢谢,
叶先义
what Mysql version are you using?
Mysql8 INFORMATION SCHEMA does not have the table INNODB_LOCKS
mysql> show tables like '%innodb%';
+-----------------------------------------+
| Tables_in_information_schema (%INNODB%) |
+-----------------------------------------+
| INNODB_BUFFER_PAGE |
| INNODB_BUFFER_PAGE_LRU |
| INNODB_BUFFER_POOL_STATS |
| INNODB_CACHED_INDEXES |
| INNODB_CMP |
| INNODB_CMPMEM |
| INNODB_CMPMEM_RESET |
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_PER_INDEX_RESET |
| INNODB_CMP_RESET |
| INNODB_COLUMNS |
| INNODB_DATAFILES |
| INNODB_FIELDS |
| INNODB_FOREIGN |
| INNODB_FOREIGN_COLS |
| INNODB_FT_BEING_DELETED |
| INNODB_FT_CONFIG |
| INNODB_FT_DEFAULT_STOPWORD |
| INNODB_FT_DELETED |
| INNODB_FT_INDEX_CACHE |
| INNODB_FT_INDEX_TABLE |
| INNODB_INDEXES |
| INNODB_METRICS |
| INNODB_TABLES |
| INNODB_TABLESPACES |
| INNODB_TABLESPACES_BRIEF |
| INNODB_TABLESTATS |
| INNODB_TEMP_TABLE_INFO |
| INNODB_TRX |
| INNODB_VIRTUAL |
+-----------------------------------------+
30 rows in set (0.01 sec)
您 link 阅读了一些 MySQL 5.7 文档,所以我假设您使用的是 5.7。
InnoDB 中唯一的 table 锁是 元数据锁 ,也称为 意向锁 ,在此处记录:https://dev.mysql.com/doc/refman/5.5/en/innodb-locking.html#innodb-intention-locks
任何想要执行某些 DML 操作以读取或写入 table(即 SELECT/INSERT/UPDATE/DELETE)中的记录的事务都需要先获取元数据锁。多个并发会话可以获取元数据锁来做DML,并且这些不会相互冲突。
同样,元数据操作(DDL 语句 ALTER、DROP 或 TRUNCATE TABLE)在开始之前需要获取元数据锁。因此,如果存在任何事务 运行 DML 语句和 vice-versa,则 DDL 语句将被阻止。
这就是在 long-running ALTER 期间阻止 DML 查询 table 的方式。
在 MySQL 5.7 中,您可以为元数据锁设置一些 PERFORMANCE_SCHEMA 工具,但这需要相当多的工作。参见 https://www.percona.com/blog/2016/12/28/quickly-troubleshooting-metadata-locks-mysql-5-7/
在 MySQL 8.0.1 中,默认情况下有一个新的 PERFORMANCE_SCHEMA.DATA_LOCKS 来监视这些锁。这是一个例子:
mysql> select * from performance_schema.data_locks\G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4874033848:1112:140194859105464
ENGINE_TRANSACTION_ID: 15171
THREAD_ID: 49
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: mytable
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140194859105464
LOCK_TYPE: TABLE <-- TABLE lock
LOCK_MODE: IX <-- "IX" intention lock mode
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4874033848:55:4:2:140194863232024
ENGINE_TRANSACTION_ID: 15171
THREAD_ID: 49
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: mytable
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140194863232024
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: WAITING
LOCK_DATA: 1
还有一个METADATA_LOCKS table:
mysql> select * from performance_schema.metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_DURATION | LOCK_STATUS | SOURCE | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE | test | mytable | NULL | 140194860588144 | SHARED_WRITE | TRANSACTION | GRANTED | sql_parse.cc:5820 | 48 | 26 |
...
根据文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-table.html、
LOCK_TYPE of INFORMATION_SCHEMA INNODB_LOCKS Table should have 2 possible values: RECORD AND TABLE.
但是,我还没有看到那个字段是 "TABLE"。无论我尝试什么,它总是 "RECORD"。有没有人可以给我一个案例来实现 "TABLE"?
谢谢, 叶先义
what Mysql version are you using?
Mysql8 INFORMATION SCHEMA does not have the table INNODB_LOCKS
mysql> show tables like '%innodb%';
+-----------------------------------------+
| Tables_in_information_schema (%INNODB%) |
+-----------------------------------------+
| INNODB_BUFFER_PAGE |
| INNODB_BUFFER_PAGE_LRU |
| INNODB_BUFFER_POOL_STATS |
| INNODB_CACHED_INDEXES |
| INNODB_CMP |
| INNODB_CMPMEM |
| INNODB_CMPMEM_RESET |
| INNODB_CMP_PER_INDEX |
| INNODB_CMP_PER_INDEX_RESET |
| INNODB_CMP_RESET |
| INNODB_COLUMNS |
| INNODB_DATAFILES |
| INNODB_FIELDS |
| INNODB_FOREIGN |
| INNODB_FOREIGN_COLS |
| INNODB_FT_BEING_DELETED |
| INNODB_FT_CONFIG |
| INNODB_FT_DEFAULT_STOPWORD |
| INNODB_FT_DELETED |
| INNODB_FT_INDEX_CACHE |
| INNODB_FT_INDEX_TABLE |
| INNODB_INDEXES |
| INNODB_METRICS |
| INNODB_TABLES |
| INNODB_TABLESPACES |
| INNODB_TABLESPACES_BRIEF |
| INNODB_TABLESTATS |
| INNODB_TEMP_TABLE_INFO |
| INNODB_TRX |
| INNODB_VIRTUAL |
+-----------------------------------------+
30 rows in set (0.01 sec)
您 link 阅读了一些 MySQL 5.7 文档,所以我假设您使用的是 5.7。
InnoDB 中唯一的 table 锁是 元数据锁 ,也称为 意向锁 ,在此处记录:https://dev.mysql.com/doc/refman/5.5/en/innodb-locking.html#innodb-intention-locks
任何想要执行某些 DML 操作以读取或写入 table(即 SELECT/INSERT/UPDATE/DELETE)中的记录的事务都需要先获取元数据锁。多个并发会话可以获取元数据锁来做DML,并且这些不会相互冲突。
同样,元数据操作(DDL 语句 ALTER、DROP 或 TRUNCATE TABLE)在开始之前需要获取元数据锁。因此,如果存在任何事务 运行 DML 语句和 vice-versa,则 DDL 语句将被阻止。
这就是在 long-running ALTER 期间阻止 DML 查询 table 的方式。
在 MySQL 5.7 中,您可以为元数据锁设置一些 PERFORMANCE_SCHEMA 工具,但这需要相当多的工作。参见 https://www.percona.com/blog/2016/12/28/quickly-troubleshooting-metadata-locks-mysql-5-7/
在 MySQL 8.0.1 中,默认情况下有一个新的 PERFORMANCE_SCHEMA.DATA_LOCKS 来监视这些锁。这是一个例子:
mysql> select * from performance_schema.data_locks\G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4874033848:1112:140194859105464
ENGINE_TRANSACTION_ID: 15171
THREAD_ID: 49
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: mytable
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140194859105464
LOCK_TYPE: TABLE <-- TABLE lock
LOCK_MODE: IX <-- "IX" intention lock mode
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4874033848:55:4:2:140194863232024
ENGINE_TRANSACTION_ID: 15171
THREAD_ID: 49
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: mytable
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140194863232024
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: WAITING
LOCK_DATA: 1
还有一个METADATA_LOCKS table:
mysql> select * from performance_schema.metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_DURATION | LOCK_STATUS | SOURCE | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE | test | mytable | NULL | 140194860588144 | SHARED_WRITE | TRANSACTION | GRANTED | sql_parse.cc:5820 | 48 | 26 |
...