我有一个存储过程,它执行以下操作:
以下是我在Sybase ASE中的表现:
set rowcount @count
begin tran get_items
insert into #temp_table
select item
from available_item
where is_processed = 0
update available_item
set is_processed = 1
from available_item, #temp_table
where available_item.item = #temp_table.item
# select the processed items...
commit trans
我想知道这里是否有竞争条件。如果两个单独的进程同时执行此存储过程,它们是否可以选择并标记处理相同的数据?或者在交易中将它停止了吗?
如果没有,有没有办法在选定的行上持有锁?
答案 0 :(得分:0)
部分细节取决于您的表格锁定方案。所有页面,页面和行级别锁定将对您在单个表上运行并发更新的能力产生不同的影响。我假设一个页/行级方案,以允许并发。
您的查询将获取一个初始共享页面/行锁定,该锁定将升级为更新锁定,然后在更新的页面/行上执行独占行锁定。在事务期间,没有其他进程能够对所选页面/行进行更改,但是另一个进程可能会在更新之前读取所选行,这可能会导致一些不一致。
要解决这种可能性,可以将事务中的隔离级别指定为隔离级别2(可重复读取)或隔离级别3(序列化)。您可能想要了解每个级别的具体细节,以决定您要执行哪些,以及与之相关的权衡。
在您的交易中,您可以像这样使用它:
set rowcount @count
set transaction isolation level 2
...
需要注意的是,根据您在查询中获取的记录数量,您可以触发锁定升级,这可能会阻止并发事务执行,即使它们没有查看与第一个事务相同的行。默认情况下,如果服务器获取超过200页/行的锁,则服务器将尝试升级到表锁。这可以更改为显式值或值和百分比范围,并且可以在服务器,数据库或表级别进行配置。
相关文件:
Transaction: Maintaining Data Consistency and Recovery
Performance and Tuning Series: Locking and Concurrency Control
Transact-SQL Users Guide 15.7 > Transactions: Maintaining Data Consistency and Recovery