1. 程式人生 > >行鎖與行鎖出現的問題

行鎖與行鎖出現的問題

 1.瘋狂的“獨佔”行鎖


譯文:
昨天我發現了SQL SERVER一些確實很怪異的行為。我有一個案例我竟然可以讀取被其他會話置了“獨佔”鎖的記錄。看到“獨佔”這個詞,你想到的一定是:一個事務擁有獨佔行鎖那麼其它事務就不能讀取該行了。但是這有特例:你可以讀取被其它被別人獨佔鎖定的行。
它花了我和同事很多時間,最終才發現到底是怎麼回事。

為了重現這種行為,你需要一個測試表,表裡有一些隨機資料。

CREATE TABLE [MyTable]
 ([Col1] bigint PRIMARY KEY CLUSTERED, [Col2] bigint)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (1,10)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (2,20)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (3,30)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (4,40)
INSERT INTO [MyTable] ([Col1], [Col2]) VALUES (5,50)

只要資料庫沒有開啟快照隔離,你可以將測試表放在任何資料庫中,而且恢復模式也對它沒有影響。
下面我們來執行一些查詢,看看會發生什麼。為了能正確地測試,你需要對同一測試表執行兩個不同的會話。為了能一直持有已分配的鎖,你需要啟動一個事務、執行一些命令,但是千萬不要結束事務。
首先在查詢分析器的第一個視窗中(我們稱之為會話1)查詢表中的某一行,並且使用提示XLOCK和ROWLOCK獲得一個獨佔的行鎖。
會話 1:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRAN
SELECT Col1 FROM [MyTable] WITH (XLOCK, ROWLOCK) WHERE [Col1] = 3

為了核實鎖的情況,我們執行sp_locks來看看到底為會話1授予了哪些鎖:

spid   dbid   ObjId       IndId  Type Resource                   Mode     Status
------ ------ ----------- ------ ---- -------------------------------- --------    ------
56     21     69575286    1      PAG  1:41                              IX       GRANT
56     21     69575286    1      KEY  (030075275214)           X        GRANT
56     21     69575286    0      TAB                                       IX       GRANT

你可以看到有一個“X”(獨佔)鎖在表的第一個鍵上。(其他的鎖是“IX”意向鎖)。現在開始第2個連線,看看如果要讀這條記錄會發生什麼?
會話 2:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRAN
SELECT Col1 FROM [MyTable] WHERE [Col1] = 3

我很希望這條語句被“掛住”,一直等到這條記錄有效為止。但我吃驚地發現這條記錄可以被非常順利的讀出。同時,sp_locks顯示系統沒有為這條指令分配任何其他鎖,即使一個共享鎖也沒有。

如果你回滾會話2(為了撇清所有其它可能的情況)然後用表提示HOLDLOCK重新執行就會得到你想要的結果了:會話2中現在需要等待會話1中的事務完成了。

為了理解所發生的事,你需要回憶一下讀提交隔離級別中的一條規則:可以讀任何已經被提交的行。這裡我們讀的行時“乾淨的”(它沒有被系統標為“髒的”),此時系統優化器會決定可以直接通過索引取資料而不需要檢查鎖的情況,所以表中甚至都不需要主鍵,只要有索引包含請求的資料,行鎖就不需要了。

所以如果被鎖住的記錄並沒有變化,被請求的列包含在索引中,那麼從READ COMMITTTED隔離級別上就獨佔鎖可能就沒什麼用了。

一種解決方法是在會話2的SELECT上加“HOLDLOCK”表提示。或者你也可以真的在會話1中更新記錄,這樣該記錄就擁有獨佔鎖了(而且還被標為“髒的”)。還有一種解決方法是用PAGLOCK鎖住整個也而不僅僅是一行,此時獨佔鎖會鎖住該頁中的所有行。

網上有人發了一篇

帖子 講述了同樣的怪異行為,一個微軟員工回覆道:
“在SELECT語句中使用XLOCK並不能阻止讀。這是因為SQL SERVER在讀提交隔離級別上有一種特殊的優化,即檢查行是否已被修改,如果未被修改則忽略XLOCK。因為在讀提交隔離級別上這確實是可以接受的。”

可能最糟糕的事是沒能在聯機圖書上找到這種行為。哪怕在section about table hints 中能有一個小小的說明也是好的。知識庫KB324417 中(適用於SQL SERVER 2000)只有一點點的提示。綜合上面所有的事實,優化器選擇這種行為比較隨便,因此你的SQL程式碼中的BUG是很難被發現的。


結論:
這花了我很多時間來找出到底發生了什麼事。所以記住:在SELECT語句中使用XLOCK和ROWLOCK提示並不意味著只有你一個人能讀這些資料行。

2.UPDATE 時, 如何避免資料定位處理被阻塞

問題描述:

資料庫PUBS中的authors表,想鎖定CITY為aaa的記錄,為什麼執行下面的命令後,CITY為bbb的記錄也被鎖定了,無法進行UPDATE.

BEGIN TRANSACTION    

    SELECT * FROM authors

    WITH (HOLDLOCK)

    WHERE city='aaa'

如何才能鎖定CITY為AAA的記錄,而且CITY為BBB的記錄依然能SELECT和UPDATE?

問題分析:

應該不是被鎖住,應該只是檢索資料的時候,需要從aaa的記錄掃描到bbb的記錄,而aaa被鎖住了,所以掃描無法往下進行,這樣看起來似乎就是bbb也被鎖住了。

當然,也有可能確實是被鎖住了,SQL Server的鎖定預設是行級的,如果你的資源不足,則可能導致鎖自動升級為頁級甚至表級鎖,這樣會導致更多的記錄被鎖定。

使用下面的語句, 如果能讀出資料, 則多半是第1種情況.

SELECT *

FROM authors WITH (READPAST)

WHERE city='bbb'

如果讀不出資料, 則一般是第2種情況.

問題解決方法:

讓SELECT 和UPDATE 走不同的索引,這樣在UPDATE 的時候,不用掃描已經鎖定的資料就可以定義到記錄,UPDATE 也就不會被阻塞了

指定索引用類似下面的語句:

SELECT *

FROM authors WITH (HOLDLOCK, INDEX=索引名)

WHERE city='aaa'

UPDATE A SET

    xx = xx

FROM authors A WITH (INDEX=索引名)

WHERE city='bbb'

當然,要保證僅掃描索引就可以定義到記錄,否則可能還是會被阻塞。

補充

對於熟悉SQL Server鎖的讀者,可以通過 sp_lock,或者查詢系統表 master.dbo.syslocks、master.dbo.syslockinfo來確定行為。

相關推薦

出現的問題

 1.瘋狂的“獨佔”行鎖譯文:昨天我發現了SQL SERVER一些確實很怪異的行為。我有一個案例我竟然可以讀取被其他會話置了“獨佔”鎖的記錄。看到“獨佔”這個詞,你想到的一定是:一個事務擁有獨佔行鎖那麼其它事務就不能讀取該行了。但是這有特例:你可以讀取被其它被別人獨佔鎖定的行

、頁面

sam span 什麽 全部 str info 讀鎖 相等 技術分享 按鎖定粒度:表鎖、頁面鎖、行鎖 存儲引擎支持情況: 在具體說明之前得明白什麽是死鎖,什麽是鎖沖突 死鎖: 多個進程互相等待對方鎖的釋放 鎖沖突:一個進程等待另一個進程釋放需要的鎖 行鎖 粒度

Innodb中的

ora 加鎖 表鎖 語句 www targe 都是 速度慢 檢索 在Innodb引擎中既支持行鎖也支持表鎖,那麽什麽時候會鎖住整張表,什麽時候或只鎖住一行呢? InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,後者是通過在數據塊中對相應

關於數據庫的認識

soft 這不 class 查詢 才會 where 自動提交 height 開啟 MySQL MySQL(InnoDB存儲引擎)默認是自動提交事務的,所以這個測試,需要先將MySQL的autocommit設置為0,關閉自動提交,需要自己手動提交事務 -- 關閉自動提

事務中的

當執行事務時,相當於執行了鎖,來保持資料的一致性,但是鎖分多種,有行鎖,表鎖。行鎖就是隻鎖定那一行,那一條記錄,別的連線下的操作還可以操作這張表。表鎖就是鎖定整張表,只有當前連線執行完事務,才可以解鎖。 就效率而然,當然是行鎖好,適用與多執行緒和高併發的情況,不過行鎖對資料庫會帶來額外的開銷。表鎖高併發就

四、資料庫機制--(悲觀樂觀表級

上一章講到了資料庫事務的隔離級別以及併發事務在不同隔離級別下可能帶來的問題和解決思路,感興趣的朋友可以看一下!直接切入正題:      從字面上看,行級鎖的作用範圍肯定比表級鎖的作用範圍要小;行級鎖和表級鎖是根據鎖的粒度來區分的,行記錄,表都是資源,鎖是作用在這些資源上的。如

mysql 實驗論證 innodb表級

innodb 的行鎖是在有索引的情況下,沒有索引的表是鎖定全表的. 表鎖演示(無索引) 操作1 操作2 處於等待狀

樂觀悲觀

到你 目前 from 提高 選中 base 排它鎖 之前 準備 在多用戶環境中,在同一時間可能會有多個用戶更新相同的記錄,這會產生沖突。這就是著名的並發性問題。 典型的沖突有: l 丟失更新:一個事務的更新覆蓋了其它事務的更新結果,就是所謂的更新丟失。例如:用戶A把值從6改

悲觀樂觀

set update 每次 pda version lec 樂觀 而是 cto 1.悲觀鎖,每次使用的時候加鎖 比如入賬交易,一上來查詢賬戶的時候就select * from account where accountid = ? for update; 2.樂觀鎖,不必每

樂觀悲觀的簡單區分

個數 行數 但是 分布式系 修改 讀寫 使用場景 狀態 控制 1、鎖的出現,是因為並發讀寫同一個數據的時候,需要進行數據完備性的保護,避免臟讀、臟寫等。 2、樂觀鎖,需要在事務中加鎖,在讀取數據的時候,不必在意數據是否已經被修改了(即允許臟讀);但是在寫入數據的時候,要檢查

Java 多線程之內置顯示

blank www get java 多線程 .com pla html com www. http://www.codeceo.com/article/built-in-lock-and-display-lock.htmlJava 多線程之內置鎖與顯示鎖

[數據庫事務]詳解七: 深入理解樂觀悲觀

ood insert 影響 hiberna memcach begin 策略 goods 其它 註明: 本文轉載自http://www.hollischuang.com/archives/934在數據庫的鎖機制中介紹過,數據庫管理系統(DBMS)中的並發控制的任務是確保在

5.1.17 死的解決(遞歸)

pri XA self. TE AR 圖片 解決 OS eas 1. 排斥鎖可能會造成死鎖,先看看死鎖的現象 from threading import Thread,Lock import time mutexA=Lock() mutexB=Lock() class

Java並發問題--樂觀悲觀以及樂觀的一種實現方式-CAS

RF -- 指針 locking water 更多 錯誤 創建 判斷 首先介紹一些樂觀鎖與悲觀鎖: 悲觀鎖:總是假設最壞的情況,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。傳統的關系型數據庫裏邊就用到了很多這

mysql的樂觀悲觀

想要 附加 情況 屬性 ... str 但是 share 版本 樂觀鎖 總是認為不會產生並發問題,每次去取數據的時候總認為不會有其他線程對數據進行修改,因此不會上鎖,但是在更新時會判斷其他線程在這之前有沒有對數據進行修改,一般會使用版本號機制或CAS操作實現。 例如: 有這

深入理解樂觀悲觀

遇到 實現 個數 默認 ODB date 開始 安全 行數 前言在數據庫的鎖機制中介紹過,數據庫管理系統(DBMS)中的並發控制的任務是確保在多個事務同時存取數據庫中同一數據時不破壞事務的隔離性和統一性以及數據庫的統一性。 樂觀並發控制(樂觀鎖)和悲觀並發控制(悲觀鎖)是並

mysql共享排他

例子 http 再看 sha 一個數 排它 下一個 表級鎖 讀取 mysql鎖機制分為表級鎖和行級鎖,本文就和大家分享一下我對mysql中行級鎖中的共享鎖與排他鎖進行分享交流。 共享鎖又稱為讀鎖,簡稱S鎖,顧名思義,共享鎖就是多個事務對於同一數據可以共享一把鎖,都能訪問到數

Java多線程系列---“基礎篇”13之 樂觀悲觀

而是 關系型 lock color 情況 發現 mis 再次 中一 轉自:http://www.cnblogs.com/zhengbin/p/5657435.html 樂觀鎖   樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認

物件例項

public class Radio { public static synchronized void classLock() { String name = Thread.currentThread().getName(); System.out.print

Java悲觀樂觀的區別及使用場景

文章目錄 定義 適用場景 總結 定義 悲觀鎖(Pessimistic Lock) : 每次獲取資料的時候,都會擔心資料被修改,所以每次獲取資料的時候都會進行加 鎖,確保在自己使用的過程中資料不會被別人修改,使用完成