1. 程式人生 > >【MySQL技術內幕】39-外來鍵和鎖

【MySQL技術內幕】39-外來鍵和鎖

外來鍵主要用於引用完整性的約束檢查。在 InnoDB儲存引擎中,對於一個外來鍵列,如果沒有顯式地對這個列加索引, InnoDB儲存引擎自動對其加一個索引,因為這樣可以避免表鎖——這比 Oracle資料庫做得好, Oracle資料庫不會自動新增索引,使用者必須自已手動新增,這也導致了 Oracle資料庫中可能產生死鎖。 對於外來鍵值的插入或更新,首先需要查詢父表中的記錄,即 SELECT父表。但是對於父表的 SELECT操作,不是使用一致性非鎖定讀的方式,因為這樣會發生資料不一致的問題,因此這時使用的是 SELECT… LOCK IN SHARE MODE方式,即主動對父表加一個S鎖。如果這時父表上已經這樣加X鎖,子表上的操作會被阻塞,如下表所示。

外來鍵測試用例
時間 會話A 會話B
1 BEGIN
2 DELETE FROM parent WHERE id=3;
3 BEGIN
4 INSERT INTO child SELECT 2,3 #第二列是外來鍵,執行該句時被阻塞(waiting)

在上述的例子中,兩個會話中的事務都沒有進行COMMIT或ROLLBAGK操作,而會話B的操作會被阻塞。這是因為id為3的父表在會話A中已經加了一個X鎖,而此時在會話B中使用者又需要對父表中id為3的行加一個S鎖,這時INSERT的操作會被阻塞。設想如果訪問父表時,使用的是一致性的非鎖定讀,這時 Session B會讀到父表有id=3的記錄,可以進行插入操作。但是如果會話A對事務提交了,則父表中就不存在id為3的記錄。資料在父、子表就會存在不一致的情況。若這時使用者查詢INNODB_LOCKS表,會看到如下結果: