最近工作有个需求,当两个或多个用户同时操作一个表时(假如是表workflow),在第一个用户进行操作时,第二个用户的操作需要被阻断。
由于并发数比较少,但是对数据一致性要求很高,比如我这里遇到的需求是报销单只能提交一份,但是多个用户有提交权限。所以决定使用排它锁(TABLOCKX)解决此问题。
解决思路如下:先创建一个表translock,在操作workflow完成后会往里插入一条数据。每次操作workflow表时,先判断translock是否有对应的操作记录,如果有,则不允许再操作workflow
SQL代码如下:
begin transaction
if not exists (select * from translock WITH (TABLOCKX) where lock_name = '工程报销')
begin
waitfor delay '0:0:10' --模拟一个耗时操作
insert into workflow(workflow_id, workflow_name) values(1001,'工程报销')
insert into translock (lock_id, lock_name) values(1,'工程报销')
print 'Submitted'
end
else
begin
print 'Submit by other user'
end
commit
然后我们同时开启两个窗口去运行这个SQL,用户A和用户B同时执行,假如用户A第一个执行,则会发现用户B会一直等待,直到用户A得到'Submitted'消息后,用户B会得到'Submit by other user'的消息,解决了并发的问题。
不过这种方式只适合并发数很少的情况。