當事務a用常規的select語句查詢資料後想做更新或插入操作,但常規的select語句不能對這些資料提供很好的保護。其他的事務可以在a查詢之後對查詢結果進行更新或刪除的操作。
鎖定讀取語句
innodb額外的提供了兩種鎖定讀取保證資料的安全:
(1)在讀取的任何行上設定共享模式鎖定。
select..
.lock
inshare
mode
(2) for update:對於搜尋到的每一條索引記錄,鎖住行和任意遇到的索引條目,就像你對這些行使用了update語句一樣。
select..
.for
update
上述兩類語句在處理單個表中或拆分成多個表的樹結構或圖結構資料時最有用。 您從一處到另一處遍歷邊緣或樹枝,同時保留返回並更改任何這些「指標」值的權利。
鎖的釋放
當事務提交或回滾時,所有被 lock in share mode 或 for update 設定的鎖都會釋放。
鎖定讀取的前提
僅當禁用了自動提交(通過使用start transaction開始事務或將自動提交設定為0)時,才可以進行鎖定讀取。
鎖定讀取的作用域
除非在子查詢中還指定了鎖定讀取,否則外部語句中的鎖定讀取不會鎖定巢狀子查詢中表的行。 例如,以下語句不會鎖定表t2中的行。
select
*from t1 where c1 =
(select c1 from t2)
forupdate
;
以下語句則會鎖住t2中的行:
select
*from t1 where c1 =
(select c1 from t2 for
update
)for
update
;
鎖定讀取的例子
一、 lock in share mode
不同表之間的資訊有關聯時,用select … lock in share mode 查詢乙個表的資訊後再在另一張表中更新設想一下你想在child表中插入一行,並且事先要確保這一行在parent表中有對應的記錄。你的應用程式**應該確保在此操作序列中的引用完整性。
錯誤的做法是:先用一致性讀取查詢parent表,確保parent表中對應的行存在,然後在child中插入一行。因為在你使用 select 和 update 之間,其他的會話很有可能已將把對應的parent表中的記錄刪除了,而你並沒有察覺到。
為了避免這種潛在的隱患,使用lock in share mode:
select
*from parent where name =
'jones'
lock
inshare
mode
;
在使用lock in share mode查詢完parent表中的name為jones的記錄後,你可以安全的在child表中新增記錄並且提交事務。其他的會話如果想獲取parent表中這行記錄的排他鎖必去等你的事務結束。
二、for update
同乙個表中的字段值在更新時依賴於先前的值,用for update更新。設想一下在 child_codes 表中有乙個用於統計child個數的整型欄位counter_field ,該欄位用於唯一標示child表中的每乙個child。
不要用一致性讀取或者共享模式的讀取來讀取計數器的當前值,因為不同的使用者在更新前可能會查詢到相同的值,當他們將相同的更新值插入時,會出現重複鍵的錯誤。
lock in share mode在這種情況下不好使的原因是:當兩個事務在共享模式下同時讀取一條記錄時,如果他們接下來都要做更新操作,那麼就必須等對方釋放鎖,從而陷入死鎖。
如果想讀取並增加counter_field值,先要用 for update 的鎖定讀取,然後在更新counter_field值:
select counter_field from child_codes for
update
;update child_codes set counter_field = counter_field +
1;
select … for update 語句會讀取最新的值,並在在讀取的每一行上設定排他鎖。因此,它設定了與包含搜尋條件的update相同的鎖。
前面的描述只是展示 select … for update 如何工作的示例。 在mysql實際操作中,僅通過單次訪問表就可以完成生成唯一識別符號的特定任務:
update child_codes set counter_field = last_insert_id(counter_field +1)
;select last_insert_id(
);
select語句僅檢索識別符號資訊(用於當前連線)。 它不訪問任何表。 innodb外來鍵造成的鎖定機制
innodb支援外來鍵,但是由於外來鍵,也會對innodb表增加鎖定機制 所有的外來鍵相關的操作都在資料更改時,比如檢查資料完整性 增加鎖定等 假設乙個表為parent,乙個表為child,parent通過id和child的parent id相連線 在乙個session中set autocommit...
當前記錄被另一使用者鎖定,解除鎖定
被鎖的原因就是有人在你之前修改記錄,此時oracle會通過事務鎖鎖住這個記錄,而且這個修改記錄的人還沒有提交或回滾記錄,接下來你又試圖修改同一條記錄,你就會被這個事務鎖所阻塞。處理方法很簡單,可以有以下兩種方法 1.找到在你之前修改記錄的那個人,讓他在他的修改記錄的會話裡做一下 commit或rol...
InnoDB怎麼解決幻讀的?
首先說結論,在rr的隔離級別下,innodb使用mvcc和next key locks解決幻讀,mvcc解決的是普通讀 快照讀 的幻讀,next key locks解決的是當前讀情況下的幻讀。事務a,先執行 update table set name hh where id 3 結果為 ok row...