行鎖的S鎖和X鎖
Innodb實施标準的行級鎖,其中有兩種類型的鎖:
Shared lock即共享鎖,S鎖。如果事務對資料行r持有S鎖,那麼允許其它事務對資料行r持有S鎖,但不允許其它事務對資料行持有X鎖。
Exclusive lock即排它鎖,X鎖。如果事務T1對資料行r持有X鎖,那麼就不允許其它事務對資料行持有S鎖或X鎖,除非等到T1釋放r上的X鎖
意向鎖(Intention lock)
Innodb支援多粒度鎖,即允許記錄鎖(record locks)和表鎖共存(InnoDB supports multiple granularity locking which permits coexistence of record locks and locks on entire tables)。為了在多個粒度級别上實作鎖定,innodb引進了意向鎖。有兩種意向鎖:
Intention shared(IS):意向共享鎖,表示事務T将要對表中資料行加S鎖,而先在表級别上加的就是IS鎖;
Intention exclusive(IX):意向排它鎖,表示事務T将要對表中資料行加X鎖,而先在表級别上加的就是IX鎖;
意圖鎖是表鎖,它訓示事務稍後将在表資料行上加何種類型的鎖。IS鎖表示事務稍後會在資料行上加S鎖,IX鎖表示事務稍後會在資料行上加X鎖。常見的,像“select … lock in share mode”語句會加IS鎖,“select … for update”語句會加IX鎖。
是以,引入意圖鎖的目的就是為了支援多粒度鎖定,并能通過意圖鎖顯示事務鎖定了表中的某些行,或者将要鎖定表中的某些行。
意圖鎖的協定如下:
一個事務要想獲得行上的S鎖,必須先擷取該表上的IS或者更強的鎖;
一個事務要想獲得行上的X鎖,必須先擷取該表上的IX鎖。
四種鎖之間的相容性如下:

如果事務請求的鎖與現有鎖相容,則授予該事務鎖;但如果與現有鎖沖突,則不授予該事務鎖,事務需要等待現有鎖被釋放後才能擷取鎖。
說明:
個人認為,上面的S和X鎖是表級别的S和X鎖。但之前和朋友讨論,說沒有表級别的S和X鎖,隻有行級别的S和X鎖,并上面指的是行級别的S和X鎖。後來發現在姜承堯的innodb内幕這本書中,也提到上面指的是行級别的S和X鎖。
是以有些疑惑的就是:鎖的粒度不同,如何讨論相容性?更何況意圖鎖引入的目的就是為了支援mysql的多粒度鎖定。
死鎖
死鎖示範:
會話1上開啟事務T1:
mysql> start transaction;
mysql> select * from ecs_payment where pay_id=2332 lock in share mode;
+--------+----------+----------+---------+----------+-----------+------------+---------+--------+-----------+
| pay_id | pay_code | pay_name | pay_fee | pay_desc | pay_order | pay_config | enabled | is_cod | is_online |
+--------+----------+----------+---------+----------+-----------+------------+---------+--------+-----------+
| 2332 | 83 | ^{} | 4090.99 | bwlw]^k | 13 | lb^wkw] | 1 | 0 | 0 |
+--------+----------+----------+---------+----------+-----------+------------+---------+--------+-----------+
會話2上開啟事務T2:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update ecs_payment set pay_name='tiatiao' where pay_id=2332; --被卡住
會話1的事務T1再執行操作:
mysql> delete from ecs_payment where pay_id=2332;
Query OK, 1 row affected (0.00 sec)
這時再看會話2的事務T2,會輸出如下資訊:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
發生死鎖的四個必要條件:
互斥條件
不可剝奪
請求與保持
循環等待
注意:
如果InnoDB螢幕輸出的最新檢測到的死鎖部分包含如下輸出資訊:
TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH, WE WILL ROLL BACK FOLLOWING TRANSACTION
這表明鎖等待清單上的事務數量已經達到了200個的限制,超過200個事務的等待清單被視為死鎖,這個數量限制和參數LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK有關