关于SQL Server锁类型,我就不列举了,大家可以通过MSDN来了解。
http://msdn.microsoft.com/zh-cn/library/ms187373.aspx
今天我就来讲一个十分有意思的事情,是在我进行并发测试时遇到的。
众所周知,在一段涉及卖票逻辑的程序中,在卖票操作时先要查询下是否有余票,有的话这要对票加锁,然后扣票和在用户记录表添加买票记录。
Two table : [Ticket] [table_user]
Begin Transaction
select top 1* from [Ticket] with (XLOCK,ROWLOCK) where Status=1;
update [Ticket] set [Status]=2,…where…
update [table_user] set …….
End Transaction
模拟并发请求时,会发现这段代码实际执行时总是表现为表锁的现象。那么是因为在select的时候where条件没有使用primary key的缘故吗?
select * from [Ticket] with (XLOCK,ROWLOCK) where id in (select top 1 id from [Ticket] where Status=1);
仍旧不行。
Why? Why? Why? …
通过观察表现每次请求时,数据库执行这段SQL总是表现为表锁,而且查询出来的数据都是同样的一行。仔细分析,原来问题出在SQL语句上:
SQL SEVER在使用行级排他锁select时会锁住了一条记录,而且此时其他的请求仍旧能够查询到此条记录,但是会在这里阻塞。所以在模拟并发的时候,多个进程都是查询到同一条记录上,于是在测试中总是表现出表被被锁住现象。
最后我的解决方法是在select时加入一定的随机规则,尽量让多个进程不要查询在一条记录上。