SQL SERVER里的鎖機(jī)制:
成都創(chuàng)新互聯(lián)專注于貴州企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城系統(tǒng)網(wǎng)站開發(fā)。貴州網(wǎng)站建設(shè)公司,為貴州等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
NOLOCK(不加鎖)
此選項(xiàng)被選中時(shí),SQL Server 在讀取或修改數(shù)據(jù)時(shí)不加任何鎖。 在這種情況下,用戶有可能讀取到未完成事務(wù)(Uncommited Transaction)或回滾(Roll Back)中的數(shù)據(jù), 即所謂的“臟數(shù)據(jù)”。
HOLDLOCK(保持鎖)
此選項(xiàng)被選中時(shí),SQL Server 會(huì)將此共享鎖保持至整個(gè)事務(wù)結(jié)束,而不會(huì)在途中釋放。 例如,“ SELECT * FROM my_table HOLDLOCK”就要求在整個(gè)查詢過程中,保持對表的鎖定,直到查詢完成才釋放鎖定。
UPDLOCK(修改鎖)
此選項(xiàng)被選中時(shí),SQL Server 在讀取數(shù)據(jù)時(shí)使用修改鎖來代替共享鎖,并將此鎖保持至整個(gè)事務(wù)或命令結(jié)束。使用此選項(xiàng)能夠保證多個(gè)進(jìn)程能同時(shí)讀取數(shù)據(jù)但只有該進(jìn)程能修改數(shù)據(jù)。
TABLOCK(表鎖)
此選項(xiàng)被選中時(shí),SQL Server 將在整個(gè)表上置共享鎖直至該命令結(jié)束。 這個(gè)選項(xiàng)保證其他進(jìn)程只能讀取而不能修改數(shù)據(jù)。
PAGLOCK(頁鎖)
此選項(xiàng)為默認(rèn)選項(xiàng), 當(dāng)被選中時(shí),SQL Server 使用共享頁鎖。
TABLOCKX(排它表鎖)
此選項(xiàng)被選中時(shí),SQL Server 將在整個(gè)表上置排它鎖直至該命令或事務(wù)結(jié)束。這將防止其他進(jìn)程讀取或修改表中的數(shù)據(jù)。
在DB2的命令行中輸入:
update monitor switches using lock on table on
然后打開另一個(gè)DB2命令窗口執(zhí)行我的那個(gè)被吊死的Update語句。
然后在第一個(gè)DB2命令窗口執(zhí)行: [@more@]get snapshot for locks on Database_Name(你的數(shù)據(jù)庫的名字) locks.TXT
然后,可以看到第一個(gè)DB2的窗口有一個(gè)信息輸出,把這些信息輸出到TXT中,大致如下:
應(yīng)用程序句柄 = 36
應(yīng)用程序標(biāo)識 = AC100C47.IC05.00F6C6095828
序號 = 0246
應(yīng)用程序名 = java.exe
CONNECT 授權(quán)標(biāo)識 = DB2ADMIN
應(yīng)用程序狀態(tài) = UOW 正在等待
狀態(tài)更改時(shí)間 = 未收集
應(yīng)用程序代碼頁 = 1208
掛起的鎖定 = 0
總計(jì)等待時(shí)間(毫秒) = 0
應(yīng)用程序句柄 = 43
應(yīng)用程序標(biāo)識 = *LOCAL.DB2.060512054331
序號 = 2273
應(yīng)用程序名 = java.exe
CONNECT 授權(quán)標(biāo)識 = DB2ADMIN
應(yīng)用程序狀態(tài) = 聯(lián)合請求暫掛
狀態(tài)更改時(shí)間 = 未收集
應(yīng)用程序代碼頁 = 1208
掛起的鎖定 = 6
總計(jì)等待時(shí)間(毫秒) = 0
鎖定列表
鎖定名稱 = 0x031F9052000000000000000055
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 255
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部
方式 = S
鎖定名稱 = 0x26800000000000000000000044
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部
方式 = S
鎖定名稱 = 0x020006000F1700000000000052
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x00000001
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 5903
對象類型 = 行
表空間名 = USERSPACE1
表模式 = DB2ADMIN
表名 = C_USER
方式 = NS
鎖定名稱 = 0x01000000010000000500BC0056
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部變化鎖定
方式 = S
鎖定名稱 = 0x535953534E333030FD965C0641
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部方案鎖定
方式 = S
鎖定名稱 = 0x02000600000000000000000054
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x00000001
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 6
對象類型 = 表
表空間名 = USERSPACE1
表模式 = DB2ADMIN
表名 = C_USER
方式 = IS
應(yīng)用程序句柄 = 557
應(yīng)用程序標(biāo)識 = *LOCAL.DB2.060512053913
序號 = 1254
應(yīng)用程序名 = java.exe
CONNECT 授權(quán)標(biāo)識 = DB2ADMIN
應(yīng)用程序狀態(tài) = 聯(lián)合請求暫掛
狀態(tài)更改時(shí)間 = 未收集
應(yīng)用程序代碼頁 = 1208
掛起的鎖定 = 6
總計(jì)等待時(shí)間(毫秒) = 0
鎖定列表
鎖定名稱 = 0x031F9052000000000000000055
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 255
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部
方式 = S
鎖定名稱 = 0x26800000000000000000000044
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部
方式 = S
鎖定名稱 = 0x02000600071D00000000000052
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x00000001
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 7431
對象類型 = 行
表空間名 = USERSPACE1
表模式 = DB2ADMIN
表名 = C_USER
方式 = NS
鎖定名稱 = 0x01000000010000000500BC0056
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部變化鎖定
方式 = S
鎖定名稱 = 0x535953534E333030FD965C0641
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x40000000
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 0
對象類型 = 內(nèi)部方案鎖定
方式 = S
鎖定名稱 = 0x02000600000000000000000054
鎖定屬性 = 0x00000000
發(fā)行版標(biāo)志 = 0x00000001
鎖定計(jì)數(shù) = 1
掛起計(jì)數(shù) = 0
鎖定對象名 = 6
對象類型 = 表
表空間名 = USERSPACE1
表模式 = DB2ADMIN
表名 = C_USER
方式 = IS
其中應(yīng)用程序句柄43和557的狀態(tài)都是死鎖了,猜測是這2個(gè)應(yīng)用爭用DB2的表,造成死鎖,根據(jù)日志提示,在DB2的命令窗口輸入:
force application (43)
force application (557)
提示這個(gè)操作是異步的,我執(zhí)行l(wèi)ist applicaions,結(jié)果進(jìn)程中還有那2個(gè)進(jìn)程,那2個(gè)進(jìn)程可能是在執(zhí)行比較大的操作,需要耐心等待,如何還不行,則使用下面的命令來強(qiáng)制所有的應(yīng)用都停止,然后重啟DB2:
force application all
terminate
db2stop force
db2start
如果DB2在Window上,則可以使用“控制中心”-實(shí)例-右鍵“應(yīng)用程序”,可以看到當(dāng)前的鎖定情況,并且可以強(qiáng)行關(guān)閉某個(gè)進(jìn)程,也可以顯示“鎖定鏈”。
方案一:
可以將查詢的代碼單出去,新建立一個(gè)方法包含它們,在原來的service方法中調(diào)用它就好,然后在配置事務(wù)時(shí),注意別把這個(gè)方法加上事務(wù)內(nèi)。
方案二:
將sqlserver的事務(wù)級別下降一個(gè)級別,別造成鎖表。sqlserver支持鎖行的。
1?如何鎖一個(gè)表的某一行?
SET?TRANSACTION?ISOLATION?LEVEL?READ?UNCOMMITTED?
SELECT?*?FROM?table?ROWLOCK?WHERE?id?=?1?
2?鎖定數(shù)據(jù)庫的一個(gè)表?
SELECT?*?FROM?table?WITH?(HOLDLOCK)?
加鎖語句:
sybase:
update?表?set?col1=col1?where?1=0?;
MSSQL:
select?col1?from?表?(tablockx)?where?1=0?;
oracle:
LOCK?TABLE?表?IN?EXCLUSIVE?MODE?;
加鎖后其它人不可操作,直到加鎖用戶解鎖,用commit或rollback解鎖
這個(gè)和C# 沒有關(guān)系,是數(shù)據(jù)庫鎖層面的原因,你只要執(zhí)行的SQL 語句發(fā)出明確的帶鎖指令即可。
SQL Server 鎖類型(與粒度相對應(yīng))
1. HOLDLOCK: 在該表上保持共享鎖,直到整個(gè)事務(wù)結(jié)束,而不是在語句執(zhí)行完立即釋放所添加的鎖。
2. NOLOCK:不添加共享鎖和排它鎖,當(dāng)這個(gè)選項(xiàng)生效后,可能讀到未提交讀的數(shù)據(jù)或“臟數(shù)據(jù)”,這個(gè)選項(xiàng)僅僅應(yīng)用于SELECT語句。
3. PAGLOCK:指定添加頁鎖(否則通??赡芴砑颖礞i)?!?/p>
4. READCOMMITTED用與運(yùn)行在提交讀隔離級別的事務(wù)相同的鎖語義執(zhí)行掃描。默認(rèn)情況下,SQL Server 2000 在此隔離級別上操作。
5. READPAST: 跳過已經(jīng)加鎖的數(shù)據(jù)行,這個(gè)選項(xiàng)將使事務(wù)讀取數(shù)據(jù)時(shí)跳過那些已經(jīng)被其他事務(wù)鎖定的數(shù)據(jù)行,而不是阻塞直到其他事務(wù)釋放鎖,READPAST僅僅應(yīng)用于READ COMMITTED隔離性級別下事務(wù)操作中的SELECT語句操作。
6. READUNCOMMITTED:等同于NOLOCK。
7. REPEATABLEREAD:設(shè)置事務(wù)為可重復(fù)讀隔離性級別?!?/p>
8. ROWLOCK:使用行級鎖,而不使用粒度更粗的頁級鎖和表級鎖。
9. SERIALIZABLE:用與運(yùn)行在可串行讀隔離級別的事務(wù)相同的鎖語義執(zhí)行掃描。等同于 HOLDLOCK?!?/p>
10. TABLOCK:指定使用表級鎖,而不是使用行級或頁面級的鎖,SQL Server在該語句執(zhí)行完后釋放這個(gè)鎖,而如果同時(shí)指定了HOLDLOCK,該鎖一直保持到這個(gè)事務(wù)結(jié)束。
11. TABLOCKX:指定在表上使用排它鎖,這個(gè)鎖可以阻止其他事務(wù)讀或更新這個(gè)表的數(shù)據(jù),直到這個(gè)語句或整個(gè)事務(wù)結(jié)束。
12. UPDLOCK :指定在讀表中數(shù)據(jù)時(shí)設(shè)置更新 鎖(update lock)而不是設(shè)置共享鎖,該鎖一直保持到這個(gè)語句或整個(gè)事務(wù)結(jié)束,使用UPDLOCK的作用是允許用戶先讀取數(shù)據(jù)(而且不阻塞其他用戶讀數(shù)據(jù)),并且保證在后來再更新數(shù)據(jù)時(shí),這一段時(shí)間內(nèi)這些數(shù)據(jù)沒有被其他用戶修改。
下面的示例 為
--鎖表(其它事務(wù)不能讀、更新、刪除)
SELECT * FROM 表名 WITH(TABLOCKX);
這個(gè)問題要具體分析:
第一,事務(wù)隔離級別基本兩種模式,一種是阻塞式(read committed,repeatable read,serializable)
,一種是非阻塞式(read uncommitted,snapshot)。
默認(rèn)是read committed,這種情況一般在更新表的時(shí)候,如果不使用hint 提示,基本是先對表添加IX鎖,級別不算高,基本和其他鎖兼容,但是repeatable read,serializable 事務(wù)隔離級別就會(huì)先對表添加IX鎖,然后向X鎖轉(zhuǎn)化,而X鎖和大多數(shù)鎖都不兼容,容易發(fā)生表阻塞。
第二種隔離級別不會(huì)有以上問題,但是又引入了其它的問題。
以上是一種情況。
另外一種就是 鎖升級,一個(gè)鎖是96B內(nèi)存,如果太多,sqlserver就會(huì)升級為表鎖,一般是5000以上行級鎖就升級為一個(gè)表X鎖。
所以適當(dāng)?shù)奈募纸M和表分區(qū) 是有必要的。
其次就是資源互相引用導(dǎo)致事務(wù)長時(shí)間不能釋放,導(dǎo)致真正的死鎖,不過SQL2005以后,這種情況發(fā)生的概率很低。
留個(gè)問題你自己去想。
兩個(gè)SQL,兩個(gè)連接,同時(shí)執(zhí)行。
update A set A.NAME=xxx where A.id=55
update A set A.NAME=xxx where A.id=56, 如果 56 不存在你說會(huì)發(fā)生什么情況呢?
當(dāng)前標(biāo)題:sqlserver加表鎖,sqlserver數(shù)據(jù)庫鎖表如何解鎖
網(wǎng)站網(wǎng)址:http://jinyejixie.com/article48/dssopep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、網(wǎng)站營銷、移動(dòng)網(wǎng)站建設(shè)、App開發(fā)、小程序開發(fā)、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)