1. 首页
  2. IT资讯

一个有关mssql锁的帖子

 

原问题: 

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博客 ” ,链接:http://blog.itpub.net/8484829/viewspace-605576/,如需转载,请注明出处,否则将追究法律责任。

主题测试文章,只做测试使用。发布者:深沉的少年,转转请注明出处:http://www.cxybcw.com/184781.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code