存储过程与标准 select 更新,避免锁定

Stored procedures vs standard select update, avoid locks

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

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

我运行的查询是:

select counter 
from dba.counter_list 
where table_name = :TableName

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

问题是,多个用户可能会 select 访问同一行,也可能会更新同一行。

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

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

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

假设:

  • 您正在使用 Sybase ASE
  • 您的 select returns 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 获得所需行的独占锁(或 page/table 取决于 table 设计和锁定方案)
  • 有了独占锁,您可以通过一条语句检索当前值并设置新值

是否通过 SQL 批处理或存储过程调用提交上述内容由您和您的 DBA 决定...

  • 如果语句缓存被禁用,SQL 批处理将需要在每次提交到数据服务器时编译
  • 如果启用了语句缓存,并且您定期提交此 SQL 批处理,那么之前的查询计划有可能仍在 statement/procedure 缓存中,从而消除了(昂贵的)编译步骤
  • 如果先前存储的过程(查询)计划的副本不在过程缓存中,那么在将(过程)查询计划加载到过程缓存中时,您将招致(昂贵的)编译步骤
  • 在出现 syntax/logic/performance 问题时,存储过程通常更容易替换(与编辑和可能编译前端应用程序相反)
  • ...为 SQL 添加您(最不喜欢的)参数 batch vs stored proc(vs prepared statement?)vs ??? ...