S很多同學在學習數據庫理論的時候對鎖的概念不是太清楚,數據庫中有很多鎖的概念,本文試着站在初學者角度去講解數據庫鎖的概念。
數據庫是一個多用戶使用的共享資源。當多個用戶並發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的情況。若對並發操作不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的一致性。
加鎖是實現數據庫並發控制的一個非常重要的技術。當事務在對某個數據對象進行操作前,先向系統發出請求,對其加鎖。加鎖后事務就對該數據對象有了一定的控制,在該事務釋放鎖之前,其他的事務不能對此數據對象進行更新操作。![]()
首先列出數據鎖的分類:

1. 樂觀鎖
以樂觀的心態認為在數據讀取的時候不會修改數據,數據庫不做加鎖處理,在數據修改的時候由用戶自行實現。
樂觀鎖的幾種實現方式:
- 版本號
就是給數據增加一個版本標識,在數據庫上就是表中增加一個version字段,每次更新把這個字段加1,讀取數據的時候把version讀出來,更新的時候比較version,如果還是開始讀取的version就可以更新了,如果現在的version比老的version大,說明有其他事務更新了該數據,並增加了版本號,這時候得到一個無法更新的通知,用戶自行根據這個通知來決定怎么處理,比如重新開始一遍。
- 時間戳
類似於版本號方式,只是通過時間戳來判斷而已,注意時間戳要使用數據庫服務器的時間戳不能是業務系統的時間。
- 待更新字段
和版本號方式相似,只是不增加額外字段,直接使用有效數據字段做版本控制信息,因為有時候我們可能無法改變舊系統的數據庫表結構。假設有個待更新字段叫u_balance,先去讀取這個u_balance(假設值為999),更新的時候去比較數據庫中u_balance的值是不是我們期望的值(一開始讀取的那個值),如果是就把我修改的u_balance的值更新到該字段,否則更新失敗。
- 所有字段
使用所有字段做版本控制信息,只有所有字段都沒變化才會執行更新。(很准確的檢測,但是降低了程序運行的效率)
2. 悲觀鎖

就如電話亭一樣,為了保證數據的安全性,懷疑數據會被修改所有每次對數據的操作都會對數據上鎖。
悲觀鎖有兩種分類:

- 共享鎖(Share Lock):又稱作S鎖(讀鎖)
共享鎖(S鎖)是非獨占的,用於所有的讀操作,運行並發共享的資源。
SELECT … LOCK IN SHARE MODE sets a shared mode lock on any rows that are read. Other sessions can read the rows, but cannot modify them until your transaction commits. If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.【mysql】

當讀取數據的時候mysql將行設置為共享鎖模式,其它會話[Session]可以讀取行數據,但是在事務沒有提交之前不能修改數據。如果有任何行被修改但是事務沒有提交,那么你的查詢要等待事務提交拿到最新的數據。
- 排他鎖(Exclusive Lock):又稱作X鎖(寫鎖)

如果一個事務對對象加了排他鎖,其他事務就不能再給它加任何鎖了【獨占】。
For index records the search encounters, SELECT … FOR UPDATE locks the rows and any associated index entries, the same as if you issued an UPDATE statement for those rows. Other transactions are blocked from updating those rows, from doing SELECT … LOCK IN SHARE MODE, or from reading the data in certain transaction isolation levels. Consistent reads ignore any locks set on the records that exist in the read view. (Old versions of a record cannot be locked; they are reconstructed by applying undo logs on an in-memory copy of the record.)
All locks set by LOCK IN SHARE MODE and FOR UPDATE queries are released when the transaction is committed or rolled back.
Note
Locking of rows for update using SELECT FOR UPDATE only applies when autocommit is disabled (either by beginning transaction with START TRANSACTION or by setting autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked.
SELECT … FOR UPDATE 會鎖住行及任何關聯的索引條目,和你對那些行執行 update 語句相同。其他的事務會被阻塞在對這些行執行 update 操作,獲取共享鎖,或從某些事務隔離級別讀取數據等操作。所有被共享鎖和排他鎖查詢所設置的鎖都會在事務提交或者回滾之后被釋放。(使用 SELECT FOR UPDATE 為 update 操作鎖定行,只適用於 autocommit 被禁用)

- 更新鎖(Update Lock):又稱作U鎖
在修改操作的初始化階段用來鎖定可能要被修改的資源,這樣可以避免使用共享鎖造成的死鎖現象。

按照作用范圍來分,悲觀鎖可以划分為表級鎖和行級鎖
- 表級鎖 作用范圍為整個表
- 行級鎖 作用范圍為行級別
