1.查看表被鎖狀態(tài)
創(chuàng)新互聯(lián)是專業(yè)的龍陵網(wǎng)站建設公司,龍陵接單;提供成都網(wǎng)站設計、網(wǎng)站制作,網(wǎng)頁設計,網(wǎng)站設計,建網(wǎng)站,PHP網(wǎng)站建設等專業(yè)做網(wǎng)站服務;采用PHP框架,可快速的進行龍陵網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
2.查看造成死鎖的sql語句
3.查詢進程
4.解鎖(刪除進程)
5.查看正在鎖的事物? (8.0以下版本)
6.查看等待鎖的事物?(8.0以下版本)
第一步,查看行鎖使用情況,命令:
show statue like 'innodb_row_lock%';
如下圖所示:
第二步,創(chuàng)建數(shù)據(jù)庫表monitor_amount,如下圖所示:
第三步,查看innodb的狀態(tài),命令:
show innodb status \G;
如下圖所示:
第四步,向數(shù)據(jù)庫表monitor_amount插入四條記錄,如下圖所示:
第五步,再次查看innodb狀態(tài),如下圖所示:
第六步,可以利用刪除表命令來停止查看,如下圖所示:
當你開始執(zhí)行一個 ALTER ,而你遇到了可怕的“元數(shù)據(jù)鎖定等待”,我敢肯定你一定遇見過。我最近遇到了一個案例,其中被更改的表要執(zhí)行一個很小范圍的更新(100行)。ALTER 在負載測試期間一直等待了幾個小時。在停止負載測試后,ALTER 按預期在不到一秒的時間內(nèi)就完成了。那么這里發(fā)生了什么?
檢查外鍵
每當有奇數(shù)次鎖定時,我的第一直覺就是檢查外鍵。當然這張表有一些外鍵引用了一個更繁忙的表。但是這種行為似乎仍然很奇怪。對表運行 ALTER 時,會針對子表請求一個 SHARED_UPGRADEABLE 元數(shù)據(jù)鎖。還有針對父級的 SHARED_READ_ONLY 元數(shù)據(jù)鎖。
我們來看看如何根據(jù)文檔獲取元數(shù)據(jù)鎖定[1]:
如果給定鎖定有多個服務器,則首先滿足最高優(yōu)先級鎖定請求,并且與 max_write_lock_count系統(tǒng)變量有關。寫鎖定請求的優(yōu)先級高于讀取鎖定請求。
[1]:
請務必注意鎖定順序是序列化的:語句逐個獲取元數(shù)據(jù)鎖,而不是同時獲取,并在此過程中執(zhí)行死鎖檢測。
通常在考慮隊列時考慮先進先出。如果我發(fā)出以下三個語句(按此順序),它們將按以下順序完成:
1. INSERT INTO parent2. ALTER TABLE child3. INSERT INTO parent
但是當子 ALTER 語句請求對父進行讀取鎖定時,盡管排序,但兩個插入將在 ALTER 之前完成。以下是可以演示此示例的示例場景:
數(shù)據(jù)初始化:
CREATE TABLE `parent` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `child` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`val` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_parent` (`parent_id`),
CONSTRAINT `fk_parent` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB;
INSERT INTO `parent` VALUES (1, "one"), (2, "two"), (3, "three"), (4, "four");
Session 1:
start transaction;update parent set val = "four-new" where id = 4;
Session 2:
alter table child add index `idx_new` (val);
Session 3:
start transaction;update parent set val = "three-new" where id = 3;
此時,會話 1 具有打開的事務,并且處于休眠狀態(tài),并在父級上授予寫入元數(shù)據(jù)鎖定。 會話 2 具有在子級上授予的可升級(寫入)鎖定,并且正在等待父級的讀取鎖定。最后會話 3 具有針對父級的授權(quán)寫入鎖定:
mysql select * from performance_schema.metadata_locks;+-------------+-------------+-------------------+---------------+-------------+| OBJECT_TYPE | OBJECT_NAME | LOCK_TYPE ? ? ? ? | LOCK_DURATION | LOCK_STATUS |+-------------+-------------+-------------------+---------------+-------------+| TABLE ? ? ? | child ? ? ? | SHARED_UPGRADABLE | TRANSACTION ? | GRANTED ? ? | - ALTER (S2)| TABLE ? ? ? | parent ? ? ?| SHARED_WRITE ? ? ?| TRANSACTION ? | GRANTED ? ? | - UPDATE (S1)| TABLE ? ? ? | parent ? ? ?| SHARED_WRITE ? ? ?| TRANSACTION ? | GRANTED ? ? | - UPDATE (S3)| TABLE ? ? ? | parent ? ? ?| SHARED_READ_ONLY ?| STATEMENT ? ? | PENDING ? ? | - ALTER (S2)+-------------+-------------+-------------------+---------------+-------------+
請注意,具有掛起鎖定狀態(tài)的唯一會話是會話 2(ALTER)。會話 1 和會話 3 (分別在 ALTER 之前和之后發(fā)布)都被授予了寫鎖。排序失敗的地方是在會話 1 上發(fā)生提交的時候。在考慮有序隊列時,人們會期望會話 2 獲得鎖定,事情就會繼續(xù)進行。但是,由于元數(shù)據(jù)鎖定系統(tǒng)的優(yōu)先級性質(zhì),會話 3 具有鎖定,會話 2 仍然等待。
如果另一個寫入會話進入并啟動新事務并獲取針對父表的寫鎖定,則即使會話 3 完成,ALTER 仍將被阻止。
只要我保持一個對父表打開元數(shù)據(jù)鎖定的活動事務,子表上的 ALTER 將永遠不會完成。更糟糕的是,由于子表上的寫鎖定成功(但是完整語句正在等待獲取父讀鎖定),所以針對子表的所有傳入讀取請求都將被阻止!
另外,請考慮一下您通常如何對無法完成的語句進行故障排除。您查看已經(jīng)打開較長時間的事務(在進程列表和 InnoDB 狀態(tài)中)。但由于阻塞線程現(xiàn)在比 ALTER 線程更年輕,因此您將看到的最舊的事務/線程是 ALTER 。
這正是這種情況下發(fā)生的情況。在準備發(fā)布時,我們的客戶端正在運行 ALTER 語句并結(jié)合負載測試(一種非常好的做法!)以確保順利發(fā)布。問題是負載測試保持對父表打開一個活動的寫事務。這并不是說它只是一直在寫,而是有多個線程,一個總是活躍的。 這阻止了 ALTER 完成并阻止對相對靜態(tài)的子表的隨后的讀請求。
幸運的是,這個問題有一個解決方案(除了從設計模式中驅(qū)逐外鍵)。變量?max_write_lock_count[2]?可用于允許在寫入鎖定之后在讀取鎖定之前授予讀取鎖定連續(xù)寫鎖。默認情況下,此變量設置為 18446744073709551615,如果你對該表發(fā)出 10,000 次寫入/秒,那么你的讀將被鎖定 5800 萬年……
以下五種方法可以快速定位全局鎖的位置,僅供參考。
方法1:利用 metadata_locks 視圖
此方法僅適用于 MySQL 5.7 以上版本,該版本 performance_schema 新增了 metadata_locks,如果上鎖前啟用了元數(shù)據(jù)鎖的探針(默認是未啟用的),可以比較容易的定位全局鎖會話。
方法2:利用 events_statements_history 視圖此方法適用于 MySQL 5.6 以上版本,啟用 performance_schema.eventsstatements_history(5.6 默認未啟用,5.7 默認啟用),該表會 SQL 歷史記錄執(zhí)行,如果請求太多,會自動清理早期的信息,有可能將上鎖會話的信息清理掉。
方法3:利用 gdb 工具如果上述兩種都用不了或者沒來得及啟用,可以嘗試第三種方法。利用 gdb 找到所有線程信息,查看每個線程中持有全局鎖對象,輸出對應的會話 ID,為了便于快速定位,我寫成了腳本形式。也可以使用 gdb 交互模式,但 attach mysql 進程后 mysql 會完全 hang 住,讀請求也會受到影響,不建議使用交互模式。
方法4:show processlist
如果備份程序使用的特定用戶執(zhí)行備份,如果是 root 用戶備份,那 time 值越大的是持鎖會話的概率越大,如果業(yè)務也用 root 訪問,重點是 state 和 info 為空的,這里有個小技巧可以快速篩選,篩選后嘗試 kill 對應 ID,再觀察是否還有 wait global read lock 狀態(tài)的會話。
方法5:重啟試試!
網(wǎng)站題目:mysql怎么判斷鎖住 mysql查看死鎖和解除鎖
文章地址:http://jinyejixie.com/article40/dodhgeo.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供域名注冊、面包屑導航、網(wǎng)頁設計公司、搜索引擎優(yōu)化、全網(wǎng)營銷推廣、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)