1. 程式人生 > >mysql 死鎖簡單分析

mysql 死鎖簡單分析

-- hand ODB star 資源 無法 作用 dex size

  • mysql都有什麽鎖
  • MySQL有三種鎖的級別:頁級、表級、行級,內存級(latch)。

    表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,並發度最低。

    行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,並發度也最高。

    頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,並發度一般

    算法:

    next KeyLocks鎖,同時鎖住記錄(數據),並且鎖住記錄前面的Gap

    Gap鎖,不鎖記錄,僅僅記錄前面的Gap

    Recordlock鎖(鎖數據,不鎖Gap)

    所以其實 Next-KeyLocks=Gap鎖+ Recordlock鎖

    1. 什麽情況下會造成死鎖

    所謂死鎖 DeadLock 是指兩個或兩個以上的進程在執行過程中,
    因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去.
    此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等竺的進程稱為死鎖進程.
    表級鎖不會產生死鎖.所以解決死鎖主要還是針對於最常用的InnoDB.

    死鎖的關鍵在於:兩個(或以上)的Session加鎖的順序不一致。

    那麽對應的解決死鎖問題的關鍵就是:讓不同的session加鎖有次序

    4,下面就簡單來重現一下死鎖:

    死鎖重現:
    事務A:
    root@test 16:01>select connection_id();
    +-----------------+

    | connection_id() |
    +-----------------+
    | 47274 |
    +-----------------+
    1 row in set (0.01 sec)

    root@test 16:02>set autocommit =0;
    Query OK, 0 rows affected (0.00 sec)

    root@test 16:02>select * from t where id =1 for update;
    +----+
    | id |
    +----+
    | 1 |
    +----+
    1 row in set (0.00 sec)

    root@test 16:02>select * from t where id =2 for update;

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
    root@test 16:03>

    事務B:
    root@test 16:02>select connection_id();
    +-----------------+
    | connection_id() |
    +-----------------+
    | 47272 |
    +-----------------+
    1 row in set (0.00 sec)

    root@test 16:02>set autocommit =0;
    Query OK, 0 rows affected (0.00 sec)

    root@test 16:02>select * from t where id =2 for update;
    +----+
    | id |
    +----+
    | 2 |
    +----+
    1 row in set (0.00 sec)

    root@test 16:03>select * from t where id =1 for update;
    +----+
    | id |
    +----+
    | 1 |
    +----+
    1 row in set (5.53 sec)

    ===========================================

    死鎖信息:

    LATEST DETECTED DEADLOCK

    2018-10-19 16:03:14 7f9612b6d700
    (1) TRANSACTION:
    TRANSACTION 870600, ACTIVE 11 sec starting index read
    mysql tables in use 1, locked 1
    LOCK WAIT 3 lock struct(s), heap size 360, 2 row lock(s)
    MySQL thread id 47272, OS thread handle 0x7f9612e38700, query id 1112421 127.0.0.1 root statistics
    select
    from t where id =1 for update
    ** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 330 page no 3 n bits 72 index PRIMARY of table test.t trx id 870600 lock_mode X locks rec but not gap waiting
    (2) TRANSACTION:
    TRANSACTION 870599, ACTIVE 22 sec starting index read
    mysql tables in use 1, locked 1
    3 lock struct(s), heap size 360, 2 row lock(s)
    MySQL thread id 47274, OS thread handle 0x7f9612b6d700, query id 1112422 127.0.0.1 root statistics
    select * from t where id =2 for update
    (2) HOLDS THE LOCK(S):
    RECORD LOCKS space id 330 page no 3 n bits 72 index PRIMARY of table test.t trx id 870599 lock_mode X locks rec but not gap
    (2) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 330 page no 3 n bits 72 index PRIMARY of table test.t trx id 870599 lock_mode X locks rec but not gap waiting
    *** WE ROLL BACK TRANSACTION (2)

    5分析:
    1,這上面是顯示是事務產生死鎖的sql並打印出相應所持和等待的鎖
    2,上面的信息並沒有輸出事務死鎖之前的sql,所以可以直接堆出兩個事務執行的sql使他們相互持有了對方等待的鎖
    3,造成死鎖是必然的,慢sql和不合理的業務的邏輯是造成死鎖過多的主要原因

    重要的事情說三遍:優化sql,優化業務,優化邏輯

    mysql 死鎖簡單分析