【问题标题】:Stored procedures vs standard select update, avoid locks存储过程与标准选择更新,避免锁定
【发布时间】:2017-09-26 16:12:58
【问题描述】:

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

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

我运行的查询是:

select counter 
from dba.counter_list 
where table_name = :TableName

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

问题在于,可能会发生多个用户选择同一行的情况,并且他们也可能更新同一行。

【问题讨论】:

  • 请发布您现有的代码并解释您与锁有关的确切问题。
  • @PM77-1 我做到了,谢谢
  • 锁是高度特定于供应商的 - 所以请添加标签以指定您使用的是mysqlpostgresqlsql-serveroracle 还是db2 - 或完全不同的东西。
  • SQL 不是数据库 - 它是一种查询语言。您使用的是什么具体的 RDBMS?甲骨文? mysql? PostgreSQL?火鸟?还有什么?
  • 将它们放在一个 transaction 中会影响锁定。我不知道将它们放在存储过程中会有很大的影响。

标签: sql locking sybase database-locking


【解决方案1】:

假设:

  • 您使用的是 Sybase ASE
  • 您的selectcounter 返回单个值
  • 您可能需要旧的 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 批处理,那么以前的查询计划仍有可能在语句/过程缓存中,从而消除(昂贵的)编译步骤
  • 如果以前存储的 proc(查询)计划的副本不在过程缓存中,那么在将(proc)查询计划加载到过程缓存中时,您将执行(代价高昂的)编译步骤
  • 如果出现语法/逻辑/性能问题(与编辑和可能编译前端应用程序相反),存储过程通常更容易替换
  • ... 为 SQL 批处理与存储过程(与准备好的语句?)与 ??? 添加您(最不喜欢的)参数...

【讨论】:

  • 非常感谢您的帮助,非常好地表达和解释!
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2011-10-11
    • 1970-01-01
    相关资源
    最近更新 更多