0

为了检索 ID,我首先在两个后续查询中进行选择,然后进行更新。

问题是我遇到了锁定行的问题。我已经读过将这两个语句 Select 和 Update 放在一个存储过程中它有助于锁定。这是真的?

我运行的查询是:

select counter 
from dba.counter_list 
where table_name = :TableName

update dba.counter_list 
set counter = :NewCounter 
where table_name = :TableName

问题是可能会发生多个用户选择同一行并且他们也可能更新同一行。

4

2 回答 2

0

表 counter_list 是否被多个客户端同时访问?

OLTP 的最佳实践是调用将在一个事务中执行更新逻辑的存储过程。

检查表 dba.counter_list 是否在 table_name 列上有索引。还要检查它是否被行级锁定。

于 2017-09-26T17:10:30.547 回答
0

假设:

  • 您正在使用 Sybase ASE
  • select返回单个值counter
  • counter除了执行更新之外,您可能出于某些目的需要旧值

考虑以下语句,它应该消除多个用户同时运行您的逻辑update可能发生的任何竞争条件:select/update

declare @counter int            -- change to the appropriate datatype

update  dba.counter_list
set     @counter = counter,     -- grab current value
        counter  = :NewCounter  -- set to new value
where   table_name = :TableName

select  @counter                -- send previous counter value to client
  • 获得update所需行(或页/表,具体取决于表设计和锁定方案)的排他锁
  • 使用排他锁,您可以检索当前值并使用单个语句设置新值

无论您是通过 SQL 批处理还是存储过程调用提交上述内容,都取决于您和您的 DBA 来决定...

  • 如果禁用了语句缓存,则每次将 SQL 批处理提交到数据服务器时都需要对其进行编译
  • 如果启用了语句缓存,并且您定期提交此 SQL 批处理,则以前的查询计划可能仍在语句/过程缓存中,从而消除了(昂贵的)编译步骤
  • 如果先前存储的过程(查询)计划的副本不在过程缓存中,那么在将(过程)查询计划加载到过程缓存中时,您将产生(昂贵的)编译步骤
  • 如果出现语法/逻辑/性能问题(与编辑和可能编译前端应用程序相反),存储过程通常更容易替换
  • ...为 SQL 批处理与存储过程(与准备好的语句?)与 ??? 添加您(最不喜欢的)参数 ...
于 2017-09-26T17:36:24.050 回答