#死鎖分析與解決 ##事務併發執行node
##事務持鎖 MySQL數據庫是以行加鎖的方式,避免不一樣事務,對同一行數據庫進行同時修改的。首先來看事務一,對張三這條記錄的Account字段進行修改,須要持有張三這條數據庫的行鎖。而後事務二也同時併發執行,事務二首先修改李四這條數據庫記錄的Corp字段,持有李四這條數據庫的行鎖。
此時兩個事務各持有一個行鎖,可是接下來事務一要持有事務二的行鎖,事務二要持有事務一的行鎖。這樣就造成了事務一與事務二相互等待,致使兩個事務都沒法繼續執行下去。數據庫
##死鎖 死鎖:指兩個或者兩個以上的事務,在執行過程當中,因爭奪鎖資源而形成的一種互相等待的現象。併發
死鎖必須是兩個或者兩個以上的事務,單個事務不可能發生死鎖。死鎖是由於爭奪鎖資源,致使相互持有鎖資源,致使相互等待。須要外部干涉的現象。dom
##死鎖產生的必要條件ide
##MySQL中的鎖 排它鎖咱們用X來表示,共享鎖咱們用S來表示。所謂排它鎖,就是和任何的鎖相互衝突,若是一個事務添加了排它鎖,無論其餘事務添加任何的鎖,都必需要等待這個事務。所謂共享鎖是指,多個事務能夠共享一把鎖,多個鎖能夠兼容,也就是說,事務一獲取共享鎖的狀況下,事務二仍是要加共享鎖,則能夠直接獲取無需等待。若是事務二須要添加一個排它鎖,則必需要等待。 oop
##加鎖方式性能
SELECT * FROM table LOCK IN SHARE MODE
SELECT * FROM table FOR UPDATE
##哪些SQL須要持有鎖 在MySQL數據庫中,全部的SELECT讀版本控制
Innodb
實現了多版本控制(MVCC),支持不加鎖快照讀。SELECT * FROM table WHERE...
須要持鎖的SQL語句code
SELECT * FROM table LOCK IN SHARE MODE
SELECT * FROM table FOR UPDATE
UPDATE FROM table SET ...
INSERT INTO...
DELETE FROM table...
增刪改的加鎖與內部的隔離級別息息相關,咱們是不容許出現幻讀的現象,有可能會加一些間隙鎖,避免出現幻讀的現象。##SQL加鎖分析 UPDATE user SET account=0 WHERE id = 1
語句,直接在行記錄進行加排他鎖,因爲快照讀的緣由此時SELECT操做是不會被阻塞的,若是是SELECT FOR UPDATE或者是SELECT IN SHARE MODE,都是會被阻塞的。orm
SELECT userName FROM user WHERE id=1 IN SHARE MODE
對行記錄添加的是共享鎖,此時,若是其餘事務要執行SELECT IN SHARE MODE的話,對同一行記錄仍是能夠進行執行的。若是外部其餘事務要執行SELECT FOR UPDATE的話,則必定會被阻塞。
##分析死鎖的經常使用辦法 MySQL數據庫會自動分析死鎖,並強制回滾代價最小的事務,不須要開發人員去關心。死鎖的解除MySQL會自動幫助咱們去作。可是咱們須要在死鎖解除之後,分析死鎖產生的SQL語句,避免死鎖再次產生。以下方法捕獲死鎖的SQL語句。
MySQL命令:
show engine innodb status
執行完畢之後,會有一大段內容出現其中,標紅部分是關於死鎖的,列出了發生死鎖時兩個等待的SQL語句,而後列出了系統強制回滾的是哪一個事務,知道了這些SQL語句,能夠分析SQL語句的加鎖方式,來調整SQL語句的順序,改變SQL語句保證按順序獲取鎖資源,這樣就能夠有效的避免死鎖的產生。
#附件 ##本身在MySQL數據庫當中,執行
show engine innodb status
獲得的結果
| InnoDB | | ===================================== 2016-10-08 22:04:17 0x7f61915e0700 INNODB MONITOR OUTPUT ===================================== Per second averages calculated from the last 45 seconds ----------------- BACKGROUND THREAD ----------------- srv_master_thread loops: 41 srv_active, 0 srv_shutdown, 12620 srv_idle srv_master_thread log flush and writes: 12661 ---------- SEMAPHORES ---------- OS WAIT ARRAY INFO: reservation count 73 OS WAIT ARRAY INFO: signal count 57 RW-shared spins 0, rounds 93, OS waits 45 RW-excl spins 0, rounds 0, OS waits 0 RW-sx spins 0, rounds 0, OS waits 0 Spin rounds per wait: 93.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx ------------ TRANSACTIONS ------------ Trx id counter 12583 Purge done for trx's n:o < 12583 undo n:o < 0 state: running but idle History list length 174 LIST OF TRANSACTIONS FOR EACH SESSION: ---TRANSACTION 421532535461264, not started 0 lock struct(s), heap size 1136, 0 row lock(s) ---TRANSACTION 421532535460352, not started 0 lock struct(s), heap size 1136, 0 row lock(s) ---TRANSACTION 421532535459440, not started 0 lock struct(s), heap size 1136, 0 row lock(s) ---TRANSACTION 421532535458528, not started 0 lock struct(s), heap size 1136, 0 row lock(s) ---TRANSACTION 421532535457616, not started 0 lock struct(s), heap size 1136, 0 row lock(s) -------- FILE I/O -------- I/O thread 0 state: waiting for completed aio requests (insert buffer thread) I/O thread 1 state: waiting for completed aio requests (log thread) I/O thread 2 state: waiting for completed aio requests (read thread) I/O thread 3 state: waiting for completed aio requests (read thread) I/O thread 4 state: waiting for completed aio requests (read thread) I/O thread 5 state: waiting for completed aio requests (read thread) I/O thread 6 state: waiting for completed aio requests (write thread) I/O thread 7 state: waiting for completed aio requests (write thread) I/O thread 8 state: waiting for completed aio requests (write thread) I/O thread 9 state: waiting for completed aio requests (write thread) Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] , ibuf aio reads:, log i/o's:, sync i/o's: Pending flushes (fsync) log: 0; buffer pool: 0 373 OS file reads, 290 OS file writes, 181 OS fsyncs 0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s ------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf: size 1, free list len 0, seg size 2, 0 merges merged operations: insert 0, delete mark 0, delete 0 discarded operations: insert 0, delete mark 0, delete 0 Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) Hash table size 34673, node heap has 0 buffer(s) 0.00 hash searches/s, 0.00 non-hash searches/s --- LOG --- Log sequence number 3162168 Log flushed up to 3162168 Pages flushed up to 3162168 Last checkpoint at 3162159 0 pending log flushes, 0 pending chkp writes 118 log i/o's done, 0.00 log i/o's/second ---------------------- BUFFER POOL AND MEMORY ---------------------- Total large memory allocated 137428992 Dictionary memory allocated 317905 Buffer pool size 8191 Free buffers 7813 Database pages 378 Old database pages 0 Modified db pages 0 Pending reads 0 Pending writes: LRU 0, flush list 0, single page 0 Pages made young 0, not young 0 0.00 youngs/s, 0.00 non-youngs/s Pages read 343, created 35, written 143 0.00 reads/s, 0.00 creates/s, 0.00 writes/s No buffer pool page gets since the last printout Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s LRU len: 378, unzip_LRU len: 0 I/O sum[0]:cur[0], unzip sum[0]:cur[0] -------------- ROW OPERATIONS -------------- 0 queries inside InnoDB, 0 queries in queue 0 read views open inside InnoDB Process ID=2247, Main thread ID=140057180620544, state: sleeping Number of rows inserted 175, updated 14, deleted 3, read 356 0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s ---------------------------- END OF INNODB MONITOR OUTPUT ============================