Sqlserver的merge into或delete語句堵塞select語句,鎖型別是LCK_M_IS
總結
sqlserver遇到delete刪除大量資料時,千萬不能直接刪除,刪除過程會堵塞不加with (nolock)的select語句,鎖型別是LCK_M_IS,delete刪除過程中,雖然加with (nolock)不斷查詢該表時看到該表資料是減少的,但是一旦cancel取消delete會話,這個cancel取消動作很漫長(也就是回滾會很漫長,之前刪除了多少行就需要回滾多少行),且cancel取消delete的操作完成後,還需要手工commit否則不加with (nolock)的select還是會堵塞,且關閉這個已經cancel的SSMS視窗會提示There are uncommitted transactions. Do you wish to commit these before closing the window?,commit後再查詢該表,發現表的資料和刪除之前一樣,而
不是大家想象中的sqlserver刪除一條資料後自動提交。所以sqlserver 刪除大量資料時,最好批次刪除,刪除5000行提交一次,這樣就算後面cancel取消delete語句,也可以很快cancel取消delete會話(也就是回滾很快,因為只需要回滾近5000條資料)
案例1,說明merge into會堵塞沒有加with (nolock)的select
會話1
MERGE INTO Corporation AS TARGET USING (select left(Symbol_Bloomberg,50) AS Symbol_Bloomberg,left(LocalCode,50)AS LOCALCODE,
left(Symbol_Thomson,50)AS Symbol_Thomson,mxid,osid FROM dbo.TRKD_WON_Mapping
where osid > 3000 AND MXID IS NOT NULL) AS SOURCE ON TARGET.Corposid = SOURCE.osid
WHEN MATCHED THEN
UPDATE SET TARGET.LOCALSYMBOL = SOURCE.LOCALCODE, TARGET.THOMSONSYMBOL= SOURCE.Symbol_Thomson,TARGET.MXID= SOURCE.MXID,
TARGET.ROWSTATUS= 'U';
MERGE INTO Corporation AS TARGET USING (select left(Symbol_Bloomberg,50) AS Symbol_Bloomberg,left(LocalCode,50)AS LOCALCODE,
left(Symbol_Thomson,50)AS Symbol_Thomson,mxid,osid FROM dbo.TRKD_WON_Mapping where osid < 3000000 AND MXID IS NOT NULL) AS SOURCE
ON TARGET.Corposid = SOURCE.osid WHEN MATCHED THEN UPDATE SET TARGET.THOMSONSYMBOL= SOURCE.Symbol_Thomson, TARGET.MXID = SOURCE.MXID,
TARGET.ROWSTATUS= 'U';
會話2,被會話1鎖住,等待LCK_M_IS鎖
select top 1 * from corporation
案例2,說明delete會堵塞沒有加with (nolock)的select
會話1
delete from marketinginterfacedb.dbo.C3_CIRC_UPDATES where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
會話2,被會話1鎖住,C3CircUpdateID是主鍵,等待LCK_M_IS鎖
select max(C3CircUpdateID) from marketinginterfacedb.dbo.C3_CIRC_UPDATES
會話3,被會話1鎖住,等待LCK_M_IS鎖
select count(*) from marketinginterfacedb.dbo.C3_CIRC_UPDATES
會話4,正常執行,沒有被會話1給鎖住
select max(C3CircUpdateID) from marketinginterfacedb.dbo.C3_CIRC_UPDATES with (nolock)
會話4,正常執行,沒有被會話1給鎖住
select count(*) from marketinginterfacedb.dbo.C3_CIRC_UPDATES with (nolock)
案例2,說明sqlserver的delete大量刪除資料時不是真正的刪除一行就自動提交了
案例2,如果會話1不是kill而是cancel取消,等cancel取消完畢後,則第6步不加 with (nolock)的select還是被堵塞,這個時候關閉這個已經cancel的SSMS視窗會提示There are uncommitted transactions. Do you wish to commit these before closing the window?,只有commit或關掉了這個cancel的cake,第六步的不加 with (nolock)的select才能正常跑,且count(*)結果還是表最初的值
C3_CIRC_UPDATES表原來292033754行資料
會話1
delete from marketinginterfacedb.dbo.C3_CIRC_UPDATES where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
會話2,看起來在delete過程中,表的資料在不斷減少
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
waitfor delay '00:00:30'
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
waitfor delay '00:00:30'
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
waitfor delay '00:00:30'
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
會話2可以正常執行,四個count(*)顯示如下結果
257243065
251250136
244925679
238778815
會話1執行20分鐘,kill會話1
會話3,會話1 剛開始處於cancel過程中,結果232428365行,看起來在delete過程中,表的資料在不斷減少
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
232428365
會話4,會話1已經kill了30分鐘還在cancel過程中,結果292033754行,說明被刪除的行並沒有被自動提交
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
292033754
會話5,會話1 kill過程中
select count(*) from dbo.C3_CIRC_UPDATES where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
--被回滾的會話1堵塞,等待LCK_M_IS鎖
會話6,會話1 kill完畢,會話1回滾耗時30分鐘,結果292033754行
select count(*) from dbo.C3_CIRC_UPDATES where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
292033754
案例3
C3_CIRC_UPDATES表原來292033754行資料
會話1
USE [marketinginterfacedb]
GO
DECLARE @r INT;
Print 'C3_CIRC_UPDATES:'
SET @r = 1;
WHILE @r > 0
BEGIN
BEGIN TRANSACTION;
DELETE TOP (5000) from marketinginterfacedb.dbo.C3_CIRC_UPDATES where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
SET @r = @@ROWCOUNT;
Print CAST(@r AS VARCHAR(10)) + ' rows deleted'
COMMIT TRANSACTION;
END
會話2,不堵塞,可以正常執行
select max(C3CircUpdateID) from marketinginterfacedb.dbo.C3_CIRC_UPDATES
會話3,不堵塞,可以正常執行,直接結果291543754
select count(*) from marketinginterfacedb.dbo.C3_CIRC_UPDATES
291543754
cancel取消會話1,發現會話1可以快速被cancel完畢,不會等待很久
會話4,會話1回滾完畢,結果291138754,比初始值292033754小了
select count(*) from dbo.C3_CIRC_UPDATES with (nolock) where CREATED_DT < '10/30/2021' and PROCESSED_TIMESTAMP is not null
291138754
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30126024/viewspace-2842532/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQLite語句(二):INSERT DELETE UPDATE SELECTSQLitedelete
- insert into select語句與select into from語句
- Oracle:select 或 inactive 會話語句產生鎖?Oracle會話
- DBeaver如何生成select,update,delete,insert語句delete
- Sqlserver、oracle中Merge的使用方法,一個merge語句搞定多個Insert,Update,Delete操作SQLServerOracledelete
- 【SQL】14 UNION 操作符、SELECT INTO 語句、INSERT INTO SELECT 語句、CREATE DATABASE 語句、CREATE TABLE 語句SQLDatabase
- delete 語句帶別名問題.delete
- SQL SELECT 語句SQL
- SQLSERVER 語句交錯引發的死鎖研究SQLServer
- 【SQL】11 SQL DELETE 語句SQLdelete
- 學習MySQL的select語句MySql
- SQL語言基礎(SELECT語句)SQL
- sqlserver dba常用的sql語句SQLServer
- Go select語句詳解Go
- INSERT...SELECT語句對查詢的表加鎖嗎
- 圖解Go select語句原理圖解Go
- Select語句執行順序
- WorkBench,DELETE 標準語句失敗delete
- flask之控制語句 if 語句與for語句Flask
- sqlserver採集欄位的sql語句SQLServer
- KunlunDB功能之insert/update/delete...returning語句delete
- 資料庫學習(一)——select語句資料庫
- SqlServer中迴圈和條件語句SQLServer
- 分支語句和迴圈語句
- Python中break語句和continue語句有什麼區別?Python
- 6. Oracle開發和應用—6.3. 基本SQL語句—6.3.4. select語句OracleSQL
- # 關於select關鍵字語句定義順序# 關於select關鍵字語句執行順序
- if 語句
- if語句
- 比CRUD多一點兒(三):UPDATE、DELETE語句delete
- 輕量ORM-SqlRepoEx (四)INSERT、UPDATE、DELETE 語句ORMSQLdelete
- mybatis 得sql語句對應簡單型別MyBatisSQL型別
- MySQL 修改int型別為bigint SQL語句拼接MySql型別
- 一條簡單的更新語句,MySQL是如何加鎖的?MySql
- js的with語句JS
- MySQL的語句MySql
- 翻譯:delete語句(已提交到MariaDB官方手冊)delete
- Mybatis如何執行Select語句,你真的知道嗎?MyBatis