Mysql 死锁过程及案例详解之插入意向锁与自增锁备份锁日志锁Insert Intention Lock Auto-increment Lock Backup Lock Log Lock
Mysql 插入意向鎖與自增鎖備份鎖日志鎖
插入意向鎖Insert Intention Lock
插入意向鎖Insert intention locks是記錄級別的,它通過“INSERT”關(guān)鍵詞來向其它的事務(wù)傳達插入的意向。插入意向鎖針對的是將要插入的記錄而不是已經(jīng)存在的記錄。下面我們通過例子來重現(xiàn)這個插入意向鎖。
示意案例
--Step1 在會話1里對city表ID大于4079的記錄進行更新操作。
USE world;
START TRANSACTION;
SELECT * FROM city WHERE ID > 4079 FOR UPDATE;
--Step2 在會話2里 新起個事務(wù)并插入一條記錄。
SELECT PS_CURRENT_THREAD_ID();
/*
PS_CURRENT_THREAD_ID()
50
*/
START TRANSACTION;
INSERT INTO world.city VALUES (4080, 'Darwin', 'AUS','Northern Territory', 146000);
?--Step3 在會話3里查看插入意向鎖的信息。這里的THREAD_ID來自Step2。
mysql> SELECT * FROM performance_schema.data_locks WHERE THREAD_ID = 50 \G
*************************** 1. row ***************************
?????????????? ENGINE: INNODB
?????? ENGINE_LOCK_ID: 140113210997976:1067:140113107561216
ENGINE_TRANSACTION_ID: 38669
??????????? THREAD_ID: 50
???????????? EVENT_ID: 75
??????? OBJECT_SCHEMA: world
????????? OBJECT_NAME: city
?????? PARTITION_NAME: NULL
??? SUBPARTITION_NAME: NULL
?????????? INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140113107561216
??????????? LOCK_TYPE: TABLE
??????????? LOCK_MODE: IX
????????? LOCK_STATUS: GRANTED
??????????? LOCK_DATA: NULL
*************************** 2. row ***************************
?????????????? ENGINE: INNODB
?????? ENGINE_LOCK_ID: 140113210997976:6:35:1:140113107558304
ENGINE_TRANSACTION_ID: 38669
??????????? THREAD_ID: 50
???????????? EVENT_ID: 75
??????? OBJECT_SCHEMA: world
????????? OBJECT_NAME: city
?????? PARTITION_NAME: NULL
??? SUBPARTITION_NAME: NULL
?????????? INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140113107558304
??????????? LOCK_TYPE: RECORD
??????????? LOCK_MODE: X,INSERT_INTENTION
????????? LOCK_STATUS: WAITING
??????????? LOCK_DATA: supremum pseudo-record
2 rows in set (0.00 sec)
這時不難發(fā)現(xiàn)回話2即THREAD_ID為50的事務(wù)當前的鎖模式為X,INSERT_INTENTION即排他的插入意向鎖,這里看到鎖定的數(shù)據(jù)是“supremum pseudo-record”即該表的上界偽記錄。這里“X”對應(yīng)next key鎖,但這里比較特殊,因為鎖的是上界偽記錄,很顯然是鎖定不了的(上界無法定義),這里其實是個gap lock即鎖定當前表的最后記錄和上界偽記錄之間的記錄。
?
自增鎖Auto-increment Lock
自增鎖Auto-increment Locks主要應(yīng)用在一個表有自增列時,確保兩個事務(wù)對表操作時有不重復(fù)的唯一的值是很有必要的。如果使用基于語句的日志記錄到二進制日志時,還有進一步的限制,因為在重放語句時,除了第一行以外的所有行都將重新創(chuàng)建自動遞增值。Innodb通過參數(shù)innodb_autoinc_lock_mode設(shè)置自增鎖。
0:traditonal (每次都會產(chǎn)生表鎖,該自增鎖是表鎖級別,且必須等待當前SQL執(zhí)行完成后或者回滾掉才會釋放。)
1:consecutive (會產(chǎn)生一個輕量鎖,無論是單一或者批量的insert SQL,可以立即獲得該鎖,并立即釋放,能保證復(fù)制,但自增值不一定嚴格連續(xù)。)
2:interleaved (不會鎖表,來一個處理一個,并發(fā)最高,所有insert種類的SQL都可以立馬獲得鎖并釋放,無法保證復(fù)制。)
備份鎖Backup Lock
備份鎖Backup Locks是mysql8.0里新引進的實例級別的鎖,它主要是保證備份時數(shù)據(jù)庫是一致的,它在備份時主要鎖定以下語句:
CREATE TABLE、CREATE TABLESPACE、RENAME TABLE、DROP TABLE、 CREATE USER、 ALTER USER、DROP USER、GRANT等。
備份鎖可以通過如下語句產(chǎn)生和收回,前提是用戶擁有BACKUP_ADMIN權(quán)限:
LOCK INSTANCE FOR BACKUP
UNLOCK INSTANCE
示意案例
-- Step1 會話1里鎖定數(shù)據(jù)庫實例
LOCK INSTANCE FOR BACKUP;
-- Step2 會話2里優(yōu)化world數(shù)據(jù)庫里的city表
use world
OPTIMIZE TABLE city;
-- Step3 會話3里查看鎖的相關(guān)信息(以mysql命令行方式執(zhí)行)
SELECT * FROM performance_schema.metadata_locks
WHERE OBJECT_TYPE = 'BACKUP LOCK'\G
*************************** 1. row ***************************
OBJECT_TYPE: BACKUP LOCK
OBJECT_SCHEMA: NULL
OBJECT_NAME: NULL
COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 4022252031312
LOCK_TYPE: SHARED
LOCK_DURATION: EXPLICIT
LOCK_STATUS: GRANTED
SOURCE: sql_backup_lock.cc:101
OWNER_THREAD_ID: 29
OWNER_EVENT_ID: 8
*************************** 2. row ***************************
OBJECT_TYPE: BACKUP LOCK
OBJECT_SCHEMA: NULL
OBJECT_NAME: NULL
COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 2520403183328
LOCK_TYPE: INTENTION_EXCLUSIVE
LOCK_DURATION: TRANSACTION
LOCK_STATUS: PENDING
SOURCE: sql_base.cc:5400
OWNER_THREAD_ID: 30
OWNER_EVENT_ID: 19
2 rows in set (0.0007 sec)
-- Step4 解鎖數(shù)據(jù)庫實例
UNLOCK INSTANCE;
在如上的例子里,會話1里進程id 29擁有一個備份鎖(back lock),而會話2里有個進程是30的在等待備份鎖釋放。這里LOCK INSTANCE FOR BACKUP是個共享鎖,而DDL語句是排他的意向鎖。
日志鎖Log Lock
在創(chuàng)建備份時,通常需要包含與備份一致的日志位置信息,在Mysql 5.7時需要加一個全局讀鎖才能獲取到這個信息,而在Mysql 8.0里InnoDB可以通過日志鎖來讀執(zhí)行的全局事務(wù)標識(global transaction identifiers)又簡稱為GTIDs,二進制日志的位置、日志序列號(log sequence number 又簡稱為LSN)),而不再是讀全局讀鎖。
日志鎖Log Lock,可以阻止修改日志相關(guān)信息的操作。
示意案例
-- 查看日志狀態(tài)。
SELECT *
FROM performance_schema.log_status\G
*************************** 1. row ***************************
SERVER_UUID: 59e3f95b-e0d6-11e8-94e8-ace2d35785be
LOCAL: {"gtid_executed": "59e3f95b-e0d6-11e8-94e8-
ace2d35785be:1-5343", "binary_log_file": "mysqlbin.
000033", "binary_log_position": 3874615}
REPLICATION: {"channels": []}
STORAGE_ENGINES: {"InnoDB": {"LSN": 7888992157, "LSN_checkpoint":
7888992157}}
總結(jié)
以上是生活随笔為你收集整理的Mysql 死锁过程及案例详解之插入意向锁与自增锁备份锁日志锁Insert Intention Lock Auto-increment Lock Backup Lock Log Lock的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 家常鱼做法?
- 下一篇: 为什么奇骏会全球第一?