.net的sqlserver事务里,delete语句如何只锁行,不锁表
发布网友
发布时间:2022-04-23 17:38
我来回答
共2个回答
热心网友
时间:2022-04-08 20:51
你理解错了!
默认sqlserver都是行数据锁定,隔离级别是 read commited 也就是读取可 提交数据。
我给你举个例子!
SELECT TOP 1000
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo].[DeleteLog]
显示结果
-----------------------------------------------
ID DeleteBy DelDate
1 admin 2008-04-13 00:00:00.000
2 admin 2008-05-04 00:00:00.000
-------------------------------------------------
表数据就两行
然后我做如下操作:
打开 SQL Server Management Studio
输入:
begin transaction
DELETE FROM [HMS].[dbo].[DeleteLog]
where ID='1'
在另一个窗口中:
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo].[DeleteLog]
where ID=1
你发现 这一个窗口被阻塞了,
但是查询
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo].[DeleteLog]
where ID=2
可以正确返回结果。 这充分证明了,sqlserver默认隔离级别是行数据锁定。
然后你此时在第一个删除窗口 中输入
rollback
,记住前面的删除不执行,只执行rollback。
此时看一下查询
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo].[DeleteLog]
where ID=1
那个窗口的结果已经出来了,阻塞被解除了。
========================================
当然了!你执行了全表检索肯定也是被阻塞的,因为删除操作还没提交啊,检索数据中又包含了你要删除的数据,当然被阻塞了。
你的问题出现在哪里了,你应该明白了吧!
解决这个问题其实很简单,不要长事务占用。检索的时候避开要删除的数据。
当然也可以改变隔离级别,sqlserver分为两类隔离级别,改成非阻塞类就可以。
但是我个人不推荐这么做。改变隔离级别可以如下方式:
set transaction isolation level read uncommitted
begin transaction
DELETE FROM [HMS].[dbo].[DeleteLog]
where ID='1'
这个删除没有提交
检索的时候
set transaction isolation level read uncommitted
SELECT
[ID]
,[DeleteBy]
,[DelDate]
FROM [dbo].[DeleteLog]
where ID=1
根本不会阻塞。 比较顺利,删除更新也一样。
这种方式 适合 数据量庞大的社交,天文数据库,企业管理不适合。
可以从侧面看出,你的程序并不优良,明白了否?
热心网友
时间:2022-04-08 22:09
默认是key锁,也就是rowlock,一行就是一个锁,,1000行就是1000个锁,当锁数量超过5000,数据库会自动把行锁升级为表锁,这样锁就变少了,占用资源就少了。
但是,全表锁定我啥也干不了啊?所以要指定paglock,例如
update t with(paglock) where Id < 2000
一页包含大概几十页上百行,这样锁的数量也比较少,不会锁全表,但如果数据特别大,例如50W行,页锁也会有5000个,同样会升级为表锁。
但50W数据够你用的了。