轉載自 :https://blog.csdn.net/youcijibi/article/details/78142767
我們在開發中也許都有感受到,數據庫的並發操作會帶來許多問題,比如丟失更新、不可重復讀、讀臟數據(幽靈數據)等等,常見的比如自動售票系統,站點1、2同時讀出剩余的票數n張,站點1售出一張票,並將n-1寫入數據庫,站點2也售出一張票並將n-1寫入數據庫,但是我們都知道,應剩余n-2張票,這就是典型的丟失數據更新的實例。為避免該類問題的產生,我們采用了封鎖機制,簡單點就是當一個線程要對數據庫進行相關操作時,先給數據庫加上適當的鎖,以此來避免其他線程對數據庫進行操作而帶來的干擾。
並發操作之所以產生錯誤,是因為不同線程並發執行事務互相干擾造成的。所以我們要對事務的並發操作進行控制,即並發控制。一般DBMS進行並發控制的方法是封鎖機制和事務機制。
封鎖就是對數據表、數據行等操作之前,先向系統請求對其加鎖,說通俗點就是操作之前先聲明權限。
封鎖的周期(環節):申請加鎖、獲得鎖權限、釋放鎖權限
最基本的封鎖類型有兩種:排它鎖(Exclusive Locks,X鎖)和共享鎖(Share Locks,S鎖)。
-
排它鎖也稱獨占鎖、寫鎖或X鎖,若sessionA獲得某數據表的排他鎖權限,那么sessionA只能對該表進行讀取或修改,其他session既不能讀取也不能修改該表,更不能對該表加任何類型的鎖,直到sessionA釋放排它鎖權限。加鎖方式:lock tables tablename write;操作如下:
sessionA:
sessionB:
從上圖操作可以看出sessionA獲得ha表排它鎖權限以后sessionB執行訪問ha表操作以后並沒用顯示ha數據而是在等待sessionA釋放鎖權限。 -
共享鎖也稱讀鎖或S鎖,若sessionA獲得某數據表的共享鎖權限,那么任何session(包括sessionA)只能對該表進行讀取,不能修改該表,sessionA可以繼續對該數據表加X鎖,其他session可以對該數據表繼續加S鎖但不能加X鎖,直到sessionA釋放共享鎖權限。加鎖方式:set tables tablename read;操作如下:
sessionA:
sessionB:
從上圖操作可以看出,sessionA獲得ha表共享鎖權限以后,sessionA和sessionB都可以訪問ha表,但是當sessionA想更改ha表時直接報錯(ERROR 1099 (HY000): Table ‘ha’ was locked with a READ lock and can’t be updated ha表有一個共享鎖不能被修改),sessionB更改ha表時並沒有顯示修改成功,而是在等待sessionA釋放共享鎖權限。 -
注意,在sessionA同時獲得某數據表的S和X鎖權限時,sessionA只能select該數據表,其他session將不能對該表進行任何操作,包括select、update、drop、delete、lock等等,直到sessionA釋放相關鎖權限。
表鎖的加鎖/解鎖方式
MyISAM 在執行查詢語句(SELECT
)前,會自動給涉及的所有表加讀鎖,在執行更新操作 (UPDATE
、DELETE
、INSERT
等)前,會自動給涉及的表加寫鎖,這個過程並不需要用戶干預,因此,用戶一般不需要直接用LOCK TABLE
命令給MyISAM表顯式加鎖。
如果用戶想要顯示的加鎖可以使用以下命令:
-
鎖定表:
LOCK TABLES tbl_name
{
READ
|
WRITE
},[
tbl_name
{
READ
|
WRITE
},…]
-
-
解鎖表:
UNLOCK TABLES
- 1
- 2
- 3
在用
LOCK TABLES
給表顯式加表鎖時,必須同時取得所有涉及到表的鎖。在執行
LOCK TABLES
后,只能訪問顯式加鎖的這些表,不能訪問未加鎖的表;如果加的是讀鎖,那么只能執行查詢操作,而不能執行更新操作。
在自動加鎖的情況下也基本如此,MyISAM 總是一次獲得 SQL 語句所需要的全部鎖。這也正是 MyISAM 表不會出現死鎖(Deadlock Free)的原因。