一、序言
上一篇講了下innodb中鎖的大約含意, 這篇說說如何查看加的什么鎖。要不然事后發(fā)生死鎖或是鎖等候都不清楚為何。
二、最底層基本表信息內(nèi)容
在學(xué)好怎么查看有什么鎖信息內(nèi)容時(shí), 必須掌握一些基本表信息內(nèi)容, 這種能幫助我們迅速清查。
過去幾篇文章內(nèi)容能夠 掌握到innodb中的鎖是在事務(wù)管理內(nèi)實(shí)行的,因此 大家先掌握下最底層的事務(wù)管理表看一下從這當(dāng)中能夠 看得出什么內(nèi)容。
2.1 information_schema.INNODB_TRX
最底層有兩個(gè)databases
mysql> show databases;
--------------------
| Database |
--------------------
| information_schema |
| mysql |
| performance_schema |
| sys |
| test_db |
--------------------
5 rows in set (0.01 sec)
能夠 挑選information_schema
查詢下邊是不是有事務(wù)管理有關(guān)的表。
mysql> use information_schema;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables like '%tr%';
-------------------------------------
| Tables_in_information_schema (%TR%) |
-------------------------------------
| CHECK_CONSTRAINTS |
| INNODB_METRICS |
| INNODB_TRX |
| Optimizer_TRACE |
| REFERENTIAL_CONSTRAINTS |
| ST_GEOMETRY_COLUMNS |
| TABLE_CONSTRAINTS |
| TRIGGERS |
-------------------------------------
8 rows in set (0.00 sec)
由此可見存有事務(wù)管理表INNODB_TRX
, 隨后看一下其表結(jié)構(gòu),隨后對于每一個(gè)字段名的表述加上
mysql> show create table INNODB_TRX;
....
INNODB_TRX | CREATE TEMPORARY TABLE `INNODB_TRX` (
# 事務(wù)管理ID
`trx_id` varchar(18) NOT NULL DEFAULT '',
# 事務(wù)管理情況, 規(guī)定值是 RUNNING,LOCK WAIT, ROLLING BACK,和 COMMITTING。
`trx_state` varchar(13) NOT NULL DEFAULT '',
# 事務(wù)管理開始時(shí)間
`trx_started` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
# 事務(wù)管理當(dāng)今等候的鎖的ID,假如TRX_STATE是LOCK WAIT;不然NULL。
`trx_requested_lock_id` varchar(105) DEFAULT NULL,
# 事務(wù)管理逐漸等候鎖的時(shí)間
`trx_wait_started` datetime DEFAULT NULL,
# 事務(wù)管理權(quán)重值, 體現(xiàn)(但不一定是精確記數(shù))變更的個(gè)數(shù)和事務(wù)管理鎖住的個(gè)數(shù)。為了更好地處理死鎖, InnoDB挑選權(quán)重值最少的事務(wù)管理做為“受害人”開展回退。不管變更和鎖住行的總數(shù)怎樣,變更非事務(wù)管理表的事務(wù)管理都被覺得比別的事務(wù)管理更重。
`trx_weight` bigint(21) unsigned NOT NULL DEFAULT '0',
# MySQL 進(jìn)程 ID。 這一id很重要,假如發(fā)覺某一事務(wù)管理一直等待沒法完畢得話,能夠 根據(jù)這一ID kill掉。
`trx_mysql_thread_id` bigint(21) unsigned NOT NULL DEFAULT '0',
# 事務(wù)管理已經(jīng)實(shí)行的 SQL 句子。
`trx_query` varchar(1024) DEFAULT NULL,
# 買賣的當(dāng)今實(shí)際操作,如果有得話;不然 NULL。
`trx_operation_state` varchar(64) DEFAULT NULL,
# InnoDB解決此事務(wù)管理的當(dāng)今 SQL 句子時(shí)應(yīng)用 的表數(shù)。
`trx_tables_in_use` bigint(21) unsigned NOT NULL DEFAULT '0',
# InnoDB當(dāng)今 SQL 句子具備行鎖 的表數(shù)。(由于這種是行鎖,而不是表鎖,雖然一些行被鎖住,但一般仍能夠 由好幾個(gè)事務(wù)管理載入和載入表。)
`trx_tables_locked` bigint(21) unsigned NOT NULL DEFAULT '0',
# 事務(wù)管理保存的鎖數(shù)。
`trx_lock_structs` bigint(21) unsigned NOT NULL DEFAULT '0',
# 此事務(wù)管理的鎖構(gòu)造在運(yùn)行內(nèi)存中占有的總尺寸。
`trx_lock_memory_bytes` bigint(21) unsigned NOT NULL DEFAULT '0',
# 此事務(wù)管理鎖住的大概總數(shù)或個(gè)數(shù)。該值很有可能包含物理學(xué)上存有但對事務(wù)管理不由此可見的刪掉標(biāo)識行。
`trx_rows_locked` bigint(21) unsigned NOT NULL DEFAULT '0',
# 此事務(wù)管理中改動(dòng)和插進(jìn)的個(gè)數(shù)。
`trx_rows_modified` bigint(21) unsigned NOT NULL DEFAULT '0',
`trx_concurrency_tickets` bigint(21) unsigned NOT NULL DEFAULT '0',
# 當(dāng)今事務(wù)管理的隔離級別。
`trx_isolation_level` varchar(16) NOT NULL DEFAULT '',
`trx_unique_checks` int(1) NOT NULL DEFAULT '0',
`trx_foreign_key_checks` int(1) NOT NULL DEFAULT '0',
`trx_last_foreign_key_error` varchar(256) DEFAULT NULL,
`trx_adaptive_hash_latched` int(1) NOT NULL DEFAULT '0',
`trx_adaptive_hash_timeout` bigint(21) unsigned NOT NULL DEFAULT '0',
`trx_is_read_only` int(1) NOT NULL DEFAULT '0',
`trx_autocommit_non_locking` int(1) NOT NULL DEFAULT '0'
) ENGINE=MEMORY DEFAULT CHARSET=utf8 |
1 row in set (0.00 sec)
以上早已對于關(guān)鍵字段名開展了注解表明,該表主要是紀(jì)錄事務(wù)管理中的一些信息內(nèi)容,十分有效,在其中便會紀(jì)錄等錢等候鎖的ID。
詳盡可以看官方網(wǎng)文本文檔:https://dev.mysql.com/doc/refman/8.0/en/information-schema-innodb-trx-table.html
在其中下列幾個(gè)字段必須尤其注意下,
TRX_ID 事務(wù)管理ID,
TRX_REQUESTED_LOCK_ID 事務(wù)管理當(dāng)今等候的鎖的ID。 假如當(dāng)今事務(wù)管理堵塞就可以看得出以前的鎖
TRX_MYSQL_THREAD_ID MySQL 進(jìn)程 ID
2.2 performance_schema.data_locks
以上事務(wù)管理表格中有紀(jì)錄當(dāng)今等候鎖的ID, 那麼這一id來源于哪兒呢?
能夠 在information_schema
performance_schema
中檢索show tables like '%lock%';
, 后邊發(fā)覺在performance_schema
下
mysql> show tables like '%lock%';
---------------------------------------
| Tables_in_performance_schema (%lock%) |
---------------------------------------
| data_lock_waits |
| data_locks |
| metadata_locks |
| rwlock_instances |
| table_lock_waits_summary_by_table |
---------------------------------------
5 rows in set (0.00 sec)
先看一下data_locks
的表構(gòu)造:
CREATE TABLE `data_locks` (
# 擁有或要求鎖的儲存模塊。
`ENGINE` varchar(32) NOT NULL,
# 儲存模塊擁有或要求的鎖的 ID。( ENGINE_LOCK_ID, ENGINE) 值的元組是唯一的。
# information_schema.INNODB_TRX.trx_requested_lock_id 就來自這
`ENGINE_LOCK_ID` varchar(128) NOT NULL,
# 要求鎖住的事務(wù)管理的儲存模塊內(nèi)部 ID
# 來源于information_schema.INNODB_TRX.TRX_ID
`ENGINE_TRANSACTION_ID` bigint(20) unsigned DEFAULT NULL,
# 建立鎖的對話的進(jìn)程 ID
`THREAD_ID` bigint(20) unsigned DEFAULT NULL,
`EVENT_ID` bigint(20) unsigned DEFAULT NULL,
`OBJECT_SCHEMA` varchar(64) DEFAULT NULL,
`OBJECT_NAME` varchar(64) DEFAULT NULL,
`PARTITION_NAME` varchar(64) DEFAULT NULL,
`SUBPARTITION_NAME` varchar(64) DEFAULT NULL,
# 鎖住數(shù)據(jù)庫索引的名字
`INDEX_NAME` varchar(64) DEFAULT NULL,
`OBJECT_INSTANCE_BEGIN` bigint(20) unsigned NOT NULL,
# 鎖的種類。該值在于儲存模塊。針對 InnoDB,容許的數(shù)值 RECORD行級鎖和 TABLE表級鎖。
`LOCK_TYPE` varchar(32) NOT NULL,
# 怎樣要求鎖住。
# 該值在于儲存模塊。為 InnoDB,規(guī)定值是 S[,GAP],X[,GAP], IS[,GAP],IX[,GAP], AUTO_INC,和 UNKNOWN。AUTO_INC和UNKNOWN 標(biāo)示空隙鎖住之外的鎖住方式 (假如存有)
`LOCK_MODE` varchar(32) NOT NULL,
# 鎖住要求的情況。
# 該值在于儲存模塊。針對 InnoDB,容許的數(shù)值 GRANTED(鎖住已擁有)和 WAITING(已經(jīng)等候鎖?。?。
`LOCK_STATUS` varchar(32) NOT NULL,
`LOCK_DATA` varchar(8192) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
PRIMARY KEY (`ENGINE_LOCK_ID`,`ENGINE`),
KEY `ENGINE_TRANSACTION_ID` (`ENGINE_TRANSACTION_ID`,`ENGINE`),
KEY `THREAD_ID` (`THREAD_ID`,`EVENT_ID`),
KEY `OBJECT_SCHEMA` (`OBJECT_SCHEMA`,`OBJECT_NAME`,`PARTITION_NAME`,`SUBPARTITION_NAME`)
) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
詳盡主要參數(shù)表述請參照: https://dev.mysql.com/doc/refman/8.0/en/performance-schema-data-locks-table.html
從上邊能夠 了解當(dāng)今事務(wù)管理假如擁有鎖的就看得出它擁有的哪些種類的鎖、鎖情況。
三、實(shí)踐活動(dòng)得真諦
1、逐漸一個(gè)事務(wù)管理1, 對某條紀(jì)錄加排他鎖:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t where id = 3 for update;
---- ------
| id | name |
---- ------
| 3 | 3 |
---- ------
1 row in set (0.00 sec)
隨后依據(jù)當(dāng)今進(jìn)程id查詢事務(wù)管理信息內(nèi)容:
mysql> select * from information_schema.INNODB_TRX where TRX_MYSQL_THREAD_ID = CONNECTION_ID() \G
*************************** 1. row ***************************
trx_id: 38441
trx_state: RUNNING
trx_started: 2021-08-22 09:26:56
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 2
trx_mysql_thread_id: 32
trx_query: select * from information_schema.INNODB_TRX where TRX_MYSQL_THREAD_ID = CONNECTION_ID()
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 1136
trx_rows_locked: 1
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec)
能夠 看得出當(dāng)今事務(wù)管理ID38441
, 鎖住個(gè)數(shù)為1行, 合乎預(yù)估。
隨后再依據(jù)事務(wù)管理ID查詢鎖信息內(nèi)容:
mysql> select * from performance_schema.data_locks where ENGINE_TRANSACTION_ID = 38441 \G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4720840032:1068:140354321295272
ENGINE_TRANSACTION_ID: 38441
THREAD_ID: 72
EVENT_ID: 246
OBJECT_SCHEMA: test_db
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140354321295272
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4720840032:11:4:2:140354330466328
ENGINE_TRANSACTION_ID: 38441
THREAD_ID: 72
EVENT_ID: 246
OBJECT_SCHEMA: test_db
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140354330466328
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 3
2 rows in set (0.00 sec)
能夠 看得出當(dāng)今事務(wù)管理相匹配2個(gè)鎖信息內(nèi)容, 第一個(gè)是表鎖:意愿排他鎖, 第二個(gè)是行鎖:排他鎖 且 非空隙鎖, 全是擁有鎖的情況, 并且鎖的紀(jì)錄也是primarKey = 3的那一條紀(jì)錄。 合乎預(yù)估。
這兒很有可能會出現(xiàn)好奇心,為什么會出現(xiàn)表鎖呢? 不了解的能夠 再看一下以前的文章內(nèi)容:https://www.cnblogs.com/yuanfy008/p/14993366.html
2、逐漸一個(gè)事務(wù)管理2, 先查詢當(dāng)今進(jìn)程id, 隨后對id=3的那一條紀(jì)錄加排他鎖。
mysql> begin;
mysql> select connection_id();
-----------------
| connection_id() |
-----------------
| 33 |
-----------------
1 row in set (0.00 sec)
mysql> select * from t where id = 3 for update;
這也是會鎖等候, 由于事務(wù)管理1占據(jù)著呢。
隨后再去此外一個(gè)對話框依據(jù)mysql線程id查詢事務(wù)管理狀況:
mysql> select * from information_schema.INNODB_TRX where TRX_MYSQL_THREAD_ID = 33 \G
*************************** 1. row ***************************
trx_id: 38445
trx_state: LOCK WAIT
trx_started: 2021-08-22 09:52:40
trx_requested_lock_id: 4720840880:11:4:2:140354330471280
trx_wait_started: 2021-08-22 09:55:56
trx_weight: 2
trx_mysql_thread_id: 33
trx_query: select * from t where id = 3 for update
trx_operation_state: starting index read
trx_tables_in_use: 1
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 1136
trx_rows_locked: 2
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec)
能夠 看得出當(dāng)今事務(wù)管理還等待另一個(gè)鎖(ID:4720840880:11:4:2:140354330471280
)的釋放出來,而這一鎖的擁有這恰好是事務(wù)管理1。合乎預(yù)估
這個(gè)時(shí)候大家再去看看這一事務(wù)管理相匹配鎖的信息內(nèi)容, 那這個(gè)時(shí)候有兩把鎖呢? 應(yīng)當(dāng)僅有一把:表鎖 - 意愿排他鎖
mysql> select * from performance_schema.data_locks where ENGINE_TRANSACTION_ID = 38445 \G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4720840880:1068:140354321297272
ENGINE_TRANSACTION_ID: 38445
THREAD_ID: 73
EVENT_ID: 31
OBJECT_SCHEMA: test_db
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140354321297272
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
1 row in set (0.00 sec)