重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
你理解错了!
为蓬溪等地区用户提供了全套网页设计制作服务,及蓬溪网站建设行业解决方案。主营业务为成都网站建设、网站建设、蓬溪网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
默认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
根本不会阻塞。 比较顺利,删除更新也一样。
这种方式 适合 数据量庞大的社交,天文数据库,企业管理不适合。
可以从侧面看出,你的程序并不优良,明白了否?
这个问题要具体分析:
第一,事务隔离级别基本两种模式,一种是阻塞式(read committed,repeatable read,serializable)
,一种是非阻塞式(read uncommitted,snapshot)。
默认是read committed,这种情况一般在更新表的时候,如果不使用hint 提示,基本是先对表添加IX锁,级别不算高,基本和其他锁兼容,但是repeatable read,serializable 事务隔离级别就会先对表添加IX锁,然后向X锁转化,而X锁和大多数锁都不兼容,容易发生表阻塞。
第二种隔离级别不会有以上问题,但是又引入了其它的问题。
以上是一种情况。
另外一种就是 锁升级,一个锁是96B内存,如果太多,sqlserver就会升级为表锁,一般是5000以上行级锁就升级为一个表X锁。
所以适当的文件分组和表分区 是有必要的。
其次就是资源互相引用导致事务长时间不能释放,导致真正的死锁,不过SQL2005以后,这种情况发生的概率很低。
留个问题你自己去想。
两个SQL,两个连接,同时执行。
update A set A.NAME=xxx where A.id=55
update A set A.NAME=xxx where A.id=56, 如果 56 不存在你说会发生什么情况呢?
如何在SQLServer中锁定某行记录
SELECT au_lname FROM authors WITH (ROWLOCK )
锁定提示 描述
HOLDLOCK 将共享锁保留到事务完成,而不是在相应的表、行或数据页不再需要时就立即释放锁。HOLDLOCK等同于SERIALIZABLE。
NOLOCK 不要发出共享锁,并且不要提供排它锁。当此选项生效时,可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅应用于 SELECT语句。
PAGLOCK 在通常使用单个表锁的地方采用页锁。
READCOMMITTED 用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQLServer 2000 在此隔离级别上操作。
READPAST 跳过锁定行。此选项导致事务跳过由其它事务锁定的行(这些行平常会显示在结果集内),而不是阻塞该事务,使其等待其它事务释放在这些行上的锁。READPAST 锁提示仅适用于运行在提交读隔离级别的事务,并且只在行级锁之后读取。仅适用于SELECT 语句。
SQL SERVER里的锁机制:
NOLOCK(不加锁)
此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到未完成事务(Uncommited Transaction)或回滚(Roll Back)中的数据, 即所谓的“脏数据”。
HOLDLOCK(保持锁)
此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。 例如,“ SELECT * FROM my_table HOLDLOCK”就要求在整个查询过程中,保持对表的锁定,直到查询完成才释放锁定。
UPDLOCK(修改锁)
此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。
TABLOCK(表锁)
此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。
PAGLOCK(页锁)
此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。
TABLOCKX(排它表锁)
此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。
就sqlserver数据库而言,每一条语句在默认事务级别下(可提交读级别)都是加锁的
如一条普通的查询,要加S锁(共享),一个更新要加U锁(更新)等等
你说的表锁、行锁只是锁的粗粒程度,如字面意思,行锁是锁住几行,表锁就是锁住整个表所在的全部数据页