ITPub博客

首页 > 数据库 > SQL Server > 一个有关mssql锁的帖子

一个有关mssql锁的帖子

原创 SQL Server 作者:sqysl 时间:2009-06-09 05:21:24 0 删除 编辑


 

原问题: 

SQL Server 2000是表锁? 

创建一个测试表TestTrans: 

---------------------------------- 

CREATE TABLE [dbo].[TestTrans] ( 

[testid] [int] NOT NULL , 

[contactname] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL , 

[contactage] [int] NULL 

) ON [PRIMARY] 

GO 

--------------------------------------------- 


打开查询分析器, 在一个窗口中运行如下语句: 

----------------------------------------------- 

begin transaction 

insert into TestTrans 

(testid, contactname, contactage) values (9, 'contact46', '32') 

----------------------------------------------- 


在查询分析器再打开一个窗口中运行如下语句 

------------------------------------- 

select count(*) from TestTrans 

------------------------------------- 


结果, 第二个窗口的查询一直在等待, 没有返回结果. 


在MySQL 5.0(InnoDB)重复以上测试, 第二个窗口不会等待立即返回结果. 

SQL Server默认是READ COMMITTED隔离等级, MySQL默认是REPEATABLE READ隔离等级. 

网友回: 

我做了个试验,给你参考下: 

试验环境 SQL SERVER 2005 EXPRESS 

准备工作: 

CREATE TABLE [dbo].[TestTrans] ( 

[testid] [int] NOT NULL , 

[contactname] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL , 

[contactage] [int] NULL 

) ON [PRIMARY] 


insert into TestTrans 

(testid, contactname, contactage) values (9, 'contact46', '32') 


insert into TestTrans 

(testid, contactname, contactage) values (10, 'contact46', '34') 


试验第1步: 

begin transaction 

select contactage 

from testtrans 

where testid=9 


第2步:新查询窗口 

update testtrans 

set contactage='45' 

where testid=10         执行OK! 


第3步:新查询窗口 

select * 

from testtrans 


结果是  9   contact46   32 

           10  contact46   45     执行OK! 

网友又回: 

试验2 

第1步:BEGIN TRANSACTION 

          update testtrans 

          set contactage='41' 

           where testid=9 


第2步:select * 

           from testtrans 

           WHERE TESTID=10  一直等待,无返回结果! 


第3步: 

        update testtrans 

            set contactage='50' 

            where testid=10      一直等待,无返回结果! 

本人回:1、SQL SERVER的锁机制是这样的: 

当对表进行修改时,系统首先会在TABLE和PAGE上加一个IU或IX锁,也就是意向锁,然后给被操作行加一个U锁或X锁,因为对表中行修改的事务没结束,这些锁是一直存在的,当你查询该表时,要加S锁,因为S锁和已经加的IU或IX模式不兼容,因此,查询只能等待。 

2、而MYSQL中的INNODB引擎在并发访问方面的特点有点类似ORACLE(MVC),在这种并发的修改和查询间不会发生等待,所以两种操作不会冲突,不会产生等待,这里我不确信的是:MYSQL中INNODB的默认事务隔离级别确实是REPEATABLE READ吗?oracle中和mssql的都是RC的,而DB2是另外一种。 

3、在sqxycl的第一个试验中,第一步因为只有一个查询,虽然从概念上讲,它可以是一个事务,可在实际中,它也许并不会启动一个事务或维持表上锁的存在,你可以跟踪一下;而在第二步中,你虽然对表进行了修改,但MSSQL中,默认每条DML都算是一个事务,完成后就提交,因此它所维持的锁随即释放掉,因此在第三步的查询中,不会产生阻塞或等待; 

而SYXYCL得最后一个试验中,理论符合该贴第一条,就是在第一步中启动了一个事务,该事务中,维持了TABLE和PAGE级的IU锁,因为该事务没提交,所以该意向锁一直维持而不释放,所以阻塞了后两步中模式和IU不兼容的操作,产生了等待。 




本人又回:再补充两点: 

1、MYSQL中innodb缺省隔离级别确实是REPEATABLE READ; 

2、通过以下代码: 

use test1 

go 

begin tran test_trans 

select * from tab1 

go 

确实能启动一个事务,而且在事务也会产生一些锁,有数据库级、对象级、行级或键级等,但多数是共享锁或意向锁,当然其间也会产生一些IX锁,但最终都会释放掉,该R事务不会与其他W事务产生RR阻塞和RW阻塞。 


[ 本帖最后由 sqysl 于 2009-6-5 06:43 编辑 ] 



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8484829/viewspace-605576/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: C++学习笔记
请登录后发表评论 登录
全部评论
大学毕业至今,一直深耕于数据库领域20余载,擅长数据库优化、数据库分析诊断、数据库规划设计等,曾任职多家知名大型企业,多次独立承担并成功上线关键大型项目。

注册时间:2008-06-27

  • 博文量
    365
  • 访问量
    725307