一个有关mssql锁的帖子

来源:这里教程网 时间:2026-03-02 10:00:39 作者:

  原问题:  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 编辑 ] 

相关推荐