資料庫中的行鎖和表鎖

2021-10-02 20:31:28 字數 3680 閱讀 1085

myisam儲存引擎只支援表鎖,這也是mysql開始幾個版本中唯一支援的鎖型別。隨著應用對事務完整性和併發性要求的不斷提高,mysql才開始開發基於事務的儲存引擎,後來慢慢出現了支援頁鎖的bdb儲存引擎和支援行鎖的innodb儲存引擎(實際 innodb是單獨的乙個公司,現在已經被oracle公司收購)。但是myisam的表鎖依然是使用最為廣泛的鎖型別。

mysql的表級鎖有兩種模式:表共享讀鎖(table read lock)表獨佔寫鎖(table write lock)

鎖模式的相容性

請求鎖模式 是否相容當前鎖模式

none

讀鎖寫鎖讀鎖是

是否寫鎖是

否否

myisam在執行查詢語句(select)前,會自動給涉及的所有表加讀鎖;

在執行更新操作(update、delete、insert等)前,會自動給涉及的表加寫鎖;

這個過程並不需要使用者干預,因此,使用者一般不需要直接用lock table命令給myisam表顯式加鎖。

上文提到過myisam表的讀和寫是序列的,但這是就總體而言的。在一定條件下,myisam表也支援查詢和插入操作的併發進行。

myisam儲存引擎有乙個系統變數concurrent_insert,專門用以控制其併發插入的行為,其值分別可以為0、1或2。

前面講過,myisam儲存引擎的讀鎖和寫鎖是互斥的,讀寫操作是序列的。那麼,乙個程序請求某個 myisam表的讀鎖,同時另乙個程序也請求同一表的寫鎖,mysql如何處理呢?答案是:寫程序先獲得鎖不僅如此,即使讀請求先到鎖等待佇列,寫請求後到,寫鎖也會插到讀鎖請求之前!**這是因為mysql認為寫請求一般比讀請求要重要。**這也正是myisam表不太適合於有大量更新操作和查詢操作應用的原因,因為,大量的更新操作會造成查詢操作很難獲得讀鎖,從而可能永遠阻塞。這種情況有時可能會變得非常糟糕!

幸好我們可以通過一些設定來調節myisam 的排程行為。

innodb實現了以下兩種型別的行鎖。

如果乙個事務請求的鎖模式與當前的鎖相容,innodb就將請求的鎖授予該事務;反之,如果兩者不相容,該事務就要等待鎖釋放。

意向鎖是innodb自動加的,不需使用者干預; 對於updatedeleteinsert語句,innodb會自動給涉及資料集加排他鎖(x);對於普通select語句,innodb不會加任何鎖;事務可以通過以下語句顯示給記錄集加共享鎖或排他鎖。

共享鎖(s):select * from table_name where ... lock in share mode

排他鎖(x):select * from table_name where ... for update

select ... in share mode獲得共享鎖,主要用在需要資料依存關係時來確認某行記錄是否存在,並確保沒有人對這個記錄進行update或者delete操作。但是如果當前事務也需要對該記錄進行更新操作,則很有可能造成死鎖,對於鎖定行記錄後需要進行更新操作的應用,應該使用select… for update方式獲得排他鎖。

innodb行鎖是通過索引上的索引項來枷鎖實現的在實際應用中,需要特別注意innodb行鎖的這一特性,不然的話,可能導致大量的鎖衝突,從而影響併發效能

當我們用範圍條件而不是相等條件檢索資料,並請求共享或排他鎖時,innodb會給符合條件的已有資料記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫做「間隙(gap)」,innodb也會對這個「間隙」加鎖,這種鎖機制就是所謂的間隙鎖(next-key鎖)。

/*舉例來說,假如emp表中只有101條記錄,其empid的值分別是 1,2,...,100,101,下面的sql:*/

select

*from emp where empid >

100for

update

;/*是乙個範圍條件的檢索,innodb不僅會對符合條件的empid值為101的記錄加鎖,也會對empid大於101(這些記錄並不存在)的「間隙」加鎖。*/

innodb使用間隙鎖的目的,一方面是為了防止幻讀,以滿足相關隔離級別的要求,對於上面的例子,要是不使用間隙鎖,如果其他事務插入了empid大於100的任何記錄,那麼本事務如果再次執行上述語句,就會發生幻讀;另外一方面,是為了滿足其恢復和複製的需要很顯然,在使用範圍條件檢索並鎖定記錄時,innodb這種加鎖機制會阻塞符合條件範圍內鍵值的併發插入,這往往會造成嚴重的鎖等待。因此,在實際應用開發中,尤其是併發插入比較多的應用,我們要盡量優化業務邏輯,盡量使用相等條件來訪問更新資料,避免使用範圍條件。

事務是由一組sql語句組成的邏輯處理單元,事務具有以下4個屬性,通常簡稱為事務的acid屬性

acid屬性相對於序列處理來說,併發事務處理能大大增加資料庫資源的利用率,提高資料庫系統的事務吞吐量,從而可以支援更多的使用者。但併發事務處理也會帶來一些問題,主要包括以下幾種情況。

為了解決上述的問題:

在上面講到的併發事務處理帶來的問題中,==「更新丟失」==通常是應該完全避免的。但防止更新丟失,並不能單靠資料庫事務控制器來解決,需要應用程式對要更新的資料加必要的鎖來解決,因此,防止更新丟失應該是應用的責任。

「髒讀」、「不可重複讀」和「幻讀」,其實都是資料庫讀一致性問題,必須由資料庫提供一定的事務隔離機制來解決

資料庫實現事務隔離的方式,基本上可分為以下兩種。

為了解決「隔離」與「併發」的矛盾,iso/ansi sql92定義了4個事務隔離級別,每個級別的隔離程度不同,允許出現的***也不同,應用可以根據自己的業務邏輯要求,通過選擇不同的隔離級別來平衡 「隔離」與「併發」的矛盾。下表很好地概括了這4個隔離級別的特性。

mysql行鎖和表鎖 關於資料庫行鎖與表鎖的認識

mysql mysql innodb儲存引擎 預設是自動提交事務的,所以這個測試,需要先將mysql的autocommit設定為0,關閉自動提交,需要自己手動提交事務 關閉自動提交 set autocommit 0 開啟事務 begin 這裡我主要針對的是悲觀鎖,其實也就是行鎖和表鎖,sql 加上 ...

Mysql 資料庫表鎖 行鎖

偏向myisam,開銷小,加鎖快,無死鎖,鎖粒度大,發生鎖衝突的概率較高,併發度較低。測試表,用於表加鎖後的讀寫可能性驗證 create table if not exists table lock id int 10 primary key not null auto increment comm...

資料庫行鎖 表鎖 記錄鎖 間隙鎖 臨鍵鎖

行鎖就是一次鎖一行或者多行記錄,mysql的行鎖是基於索引載入的,所以行鎖是要加在索引響應的行上,即命中索引。假設 table的b列為索引字段,則以下更新語句只會鎖b b 的行 update table set a a where b b 行鎖的特徵 鎖衝突概率低,併發性高,但是會有死鎖的情況出現。...