博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HOLDLOCK is not equivalent to REPEATABLE READ
阅读量:6993 次
发布时间:2019-06-27

本文共 4136 字,大约阅读时间需要 13 分钟。

 HOLDLOCK is not equivalent to REPEATABLE READ and HOLDLOCK does get range locks.  And the semantics of HOLDLOCK and SERIALIZABLE are the same - that is, they both mean that if you rerun the SELECT later in the same transaction you will get back the same result.

The difference between REPEATABLE READ and SERIALIZABLE is REPEATABLE READ guarantees that if you rerun the same select command later in the same transaction, you will get back all the rows that were returned the first time the select ran and these rows will be unchanged.  However, with REPEATABLE READ, you may get back additional, new rows that were not returned the first time.  Therefore REPEATABLE READ does not need range locks, it just puts a shared lock on every returned row.  But SERIALIZABLE not only guarantees that you will get back all the rows that were returned the first time the select ran and these rows will be unchanged, it also guarantees that no new rows will be returned.  In order to do this, it sometimes needs to do a range lock. 

So, for example, to see what REPEATABLE READ does, run

CREATE TABLE TestTable(	[name] [nvarchar](100) NOT NULL PRIMARY KEY,);INSERT INTO TestTable (name)VALUES ('H');	INSERT INTO TestTable (name)VALUES ('K');INSERT INTO TestTable (name)VALUES ('P');SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;BEGIN TRANSELECT* FROM TestTable		WHERE name Between 'J' And 'L';

Now, if you run sp_lock, you will see a KEY Shared lock on the index.  That's because only the row that is returned (name = 'K') is locked.  And if you open another connection and in the new connection run

INSERT INTO TestTable (name)values('B');SELECT * FROM TestTable;INSERT INTO TestTable (name)values('T');SELECT * FROM TestTable;INSERT INTO TestTable (name)values('M');SELECT * FROM TestTable;

Those inserts will work fine.  And the table will now have six rows.  And if you go back to the original connection, and redo the

SELECT * FROM TestTable WHERE name Between 'J' And 'N';

you will now get two rows, Name = 'K' and Name = 'M'.  This is allowed under REPEATABLE READ because the only thing REPEATABLE READ guarantees is that the rows originally returned (Name = 'K' in this case) will be returned unchanged.

But SERIALIZABLE requires that no new rows are returned.  So let's see what happens with SERIALIZABLE.  First commit or rollback all open transactions, and drop the table.  Then run

CREATE TABLE TestTable(	[name] [nvarchar](100) NOT NULL PRIMARY KEY,);INSERT INTO TestTable (name)VALUES ('H');	INSERT INTO TestTable (name)VALUES ('K');INSERT INTO TestTable (name)VALUES ('P');SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;BEGIN TRANSELECT* FROM TestTable		WHERE name Between 'J' And 'N';

Now if you run sp_lock, you will see that there are range locks.  So, let's go to another connection and try to add new rows.  If you do

INSERT INTO TestTable (name)values('B');SELECT * FROM TestTable;INSERT INTO TestTable (name)values('T');SELECT * FROM TestTable;

Then will both work fine.  That's because they will be outside the range locks.  But if you do

INSERT INTO TestTable (name)values('M');SELECT * FROM TestTable;

The insert will be blocked.  That's because inserting that row would change the result of the select query in the original connection which is not allowed with SERIALIZABLE.

OK, so now we've seen the difference between REPEATABLE READ and SERIALIZABLE, so the question is does HOLDLOCK do what REPEATABLE READ does or what SERIALIZABLE does.  To find out, commit or rollback all the open transactions, drop the TestTable table, and run

CREATE TABLE TestTable(	[name] [nvarchar](100) NOT NULL PRIMARY KEY,);INSERT INTO TestTable (name)VALUES ('H');	INSERT INTO TestTable (name)VALUES ('K');INSERT INTO TestTable (name)VALUES ('P');SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN TRANSELECT* FROM TestTable WITH (HOLDLOCK)		WHERE name Between 'J' And 'N'

Now run sp_lock.  You will see that you once again have range locks.  And when another connection tries to insert rows, it would be allowed to insert Name='B' and Name = 'T', but inserting Name='M' will be blocked.

So, HOLDLOCK is equivalent to SERIALIZABLE, not REPEATABLE READ.

转载自:

你可能感兴趣的文章
推荐android studio一个插件,可以将布局分组的
查看>>
数值型
查看>>
Hadoop集群搭建(-v1.2.1)
查看>>
内网可以访问外网,外网不能访问内网的ACL解决方法
查看>>
UITableView 编辑和删除行
查看>>
第一章,Linux常用命令
查看>>
如何在列表页面调用自定义字段值显示
查看>>
spring 使用小结
查看>>
最简单oppo系统一键激活xposed框架经验
查看>>
iptraf用法
查看>>
我的友情链接
查看>>
集算器提升Java的计算能力
查看>>
【创建型】- 建造者模式
查看>>
findbugs问题解析
查看>>
javascript---循环输出对象中的属性
查看>>
shell脚本删除N天前的文件夹
查看>>
mysql数据库管理小结
查看>>
rsync , rsync + ssh, rsync + lsyncd 多种同步方案与比较
查看>>
Mac下如何切片HLS流
查看>>
Qemu-kvm的网络模式
查看>>