2016-11-14 67 views
1

我有一个存储过程,其执行以下操作:行锁选择

  1. 从表中进行选择前N
  2. 将这些行作为处理
  3. 返回这些行到客户端

这里大概是我在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

一些细节将取决于您的表锁定方案。所有页面,页面和行级锁定对您在单个表上运行并发更新的能力有不同的影响。我假设一个页面/行级别的方案允许并发。

您的查询将抓取初始共享页面/行锁定,该锁定将升级为更新锁定,然后在更新后的页面/行上将排它锁定。没有其他进程能够在事务期间对所选页面/行进行更改,但另一个进程可能会在更新之前读取选定行,这可能会导致一些不一致。

要解决此问题,您可以将事务中的隔离级别指定为隔离级别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

+0

您好,感谢您的信息。我已经尝试在select insert查询下面的隔离2处添加,但是得到以下错误:'错误:SELECT INSERT不能用隔离级别子句指定。“你知道如何解决这个问题吗? – sam

+0

对不起,我错过了。您不能在select into处使用'isolation'。使用会话级别设置:'set transaction isolation level 2' - 我已经更新了答案。 –