MySQL逝世鎖成績剖析及處理辦法實例詳解。本站提示廣大學習愛好者:(MySQL逝世鎖成績剖析及處理辦法實例詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是MySQL逝世鎖成績剖析及處理辦法實例詳解正文
MySQL逝世鎖成績是許多法式員在項目開辟中常碰到的成績,現就MySQL逝世鎖及處理辦法詳解以下:
1、MySQL經常使用存儲引擎的鎖機制
MyISAM和MEMORY采取表級鎖(table-level locking)
BDB采取頁面鎖(page-level locking)或表級鎖,默許為頁面鎖
InnoDB支撐行級鎖(row-level locking)和表級鎖,默許為行級鎖
2、各類鎖特色
表級鎖:開支小,加鎖快;不會湧現逝世鎖;鎖定粒度年夜,產生鎖抵觸的幾率最高,並發度最低
行級鎖:開支年夜,加鎖慢;會湧現逝世鎖;鎖定粒度最小,產生鎖抵觸的幾率最低,並發度也最高
頁面鎖:開支和加鎖時光界於表鎖和行鎖之間;會湧現逝世鎖;鎖定粒度界於表鎖和行鎖之間,並發度普通
3、各類鎖的實用場景
表級鎖更合適於以查詢為主,只要大批按索引前提更新數據的運用,如Web運用
行級鎖則更合適於有年夜量按索引前提並發更新數據,同時又有並發查詢的運用,如一些在線事務處置體系
4、逝世鎖
是指兩個或兩個以上的過程在履行進程中,因爭取資本而形成的一種相互期待的景象,若無外力感化,它們都將沒法推動下去。
表級鎖不會發生逝世鎖.所以處理逝世鎖重要照樣針關於最經常使用的InnoDB.
5、逝世鎖舉例剖析
在MySQL中,行級鎖其實不是直接鎖記載,而是鎖索引。索引分為主鍵索引和非主鍵索引兩種,假如一條sql語句操作了主鍵索引,MySQL就會鎖定這條主鍵索引;假如一條語句操作了非主鍵索引,MySQL會先鎖定該非主鍵索引,再鎖定相干的主鍵索引。
在UPDATE、DELETE操作時,MySQL不只鎖定WHERE前提掃描過的一切索引記載,並且會鎖定相鄰的鍵值,即所謂的next-key locking。
例如,一個表db.tab_test,構造以下:
id:主鍵;
state:狀況;
time:時光;
索引:idx_1 (state, time)
湧現逝世鎖日記以下:
***(1) TRANSACTION: TRANSACTION 0 677833455, ACTIVE 0 sec, process no 11393, OS thread id 278546 starting index read mysql tables in use 1, locked 1 LOCK WAIT 3 lock struct(s), heap size 320 MySQL thread id 83, query id 162348740 dcnet03 dcnet Searching rows for update update tab_test set state=1064,time=now() where state=1061 and time < date_sub(now(), INTERVAL 30 minute) (義務1的sql語句) ***(1) WAITING FOR THIS LOCK TO BE GRANTED: (義務1期待的索引記載) RECORD LOCKS space id 0 page no 849384 n bits 208 index `PRIMARY` of table `db/tab_test` trx id 0 677833455 _mode X locks rec but not gap waiting Record lock, heap no 92 PHYSICAL RECORD: n_fields 11; compact format; info bits 0 0: len 8; hex 800000000097629c; asc b ;; 1: len 6; hex 00002866eaee; asc (f ;; 2: len 7; hex 00000d40040110; asc @ ;; 3: len 8; hex 80000000000050b2; asc P ;; 4: len 8; hex 800000000000502a; asc P*;; 5: len 8; hex 8000000000005426; asc T&;; 6: len 8; hex 800012412c66d29c; asc A,f ;; 7: len 23; hex 75706c6f6164666972652e636f6d2f6 8616e642e706870; asc xxx.com/;; 8: len 8; hex 800000000000042b; asc +;; 9: len 4; hex 474bfa2b; asc GK +;; 10: len 8; hex 8000000000004e24; asc N$;; *** (2) TRANSACTION: TRANSACTION 0 677833454, ACTIVE 0 sec, process no 11397, OS thread id 344086 updating or deleting, thread declared inside InnoDB 499 mysql tables in use 1, locked 1 3 lock struct(s), heap size 320, undo log entries 1 MySQL thread id 84, query id 162348739 dcnet03 dcnet Updating update tab_test set state=1067,time=now () where id in (9921180) (義務2的sql語句) *** (2) HOLDS THE LOCK(S): (義務2已取得的鎖) RECORD LOCKS space id 0 page no 849384 n bits 208 index `PRIMARY` of table `db/tab_test` trx id 0 677833454 lock_mode X locks rec but not gap Record lock, heap no 92 PHYSICAL RECORD: n_fields 11; compact format; info bits 0 0: len 8; hex 800000000097629c; asc b ;; 1: len 6; hex 00002866eaee; asc (f ;; 2: len 7; hex 00000d40040110; asc @ ;; 3: len 8; hex 80000000000050b2; asc P ;; 4: len 8; hex 800000000000502a; asc P*;; 5: len 8; hex 8000000000005426; asc T&;; 6: len 8; hex 800012412c66d29c; asc A,f ;; 7: len 23; hex 75706c6f6164666972652e636f6d2f6 8616e642e706870; asc uploadfire.com/hand.php;; 8: len 8; hex 800000000000042b; asc +;; 9: len 4; hex 474bfa2b; asc GK +;; 10: len 8; hex 8000000000004e24; asc N$;; *** (2) WAITING FOR THIS LOCK TO BE GRANTED: (義務2期待的鎖) RECORD LOCKS space id 0 page no 843102 n bits 600 index `idx_1` of table `db/tab_test` trx id 0 677833454 lock_mode X locks rec but not gap waiting Record lock, heap no 395 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 8; hex 8000000000000425; asc %;; 1: len 8; hex 800012412c66d29c; asc A,f ;; 2: len 8; hex 800000000097629c; asc b ;; *** WE ROLL BACK TRANSACTION (1) (回滾了義務1,以消除逝世鎖)
緣由剖析:
當“update tab_test set state=1064,time=now() where state=1061 and time < date_sub(now(), INTERVAL 30 minute)”履行時,MySQL會應用idx_1索引,是以起首鎖定相干的索引記載,由於idx_1長短主鍵索引,為履行該語句,MySQL還會鎖定主鍵索引。
假定“update tab_test set state=1067,time=now () where id in (9921180)”簡直同時履行時,本語句起首鎖定主鍵索引,因為須要更新state的值,所以還須要鎖定idx_1的某些索引記載。
如許第一條語句鎖定了idx_1的記載,期待主鍵索引,而第二條語句則鎖定了主鍵索引記載,而期待idx_1的記載,如許逝世鎖就發生了。
6、處理方法
拆分第一條sql,先查出相符前提的主鍵值,再依照主鍵更新記載:
select id from tab_test where state=1061 and time < date_sub(now(), INTERVAL 30 minute); update tab_test state=1064,time=now() where id in(......);
至此MySQL逝世鎖成績得以處理!