【问题标题】:Showing rows that are locked in Oracle显示在 Oracle 中锁定的行
【发布时间】:2011-03-03 14:54:33
【问题描述】:

使用 Oracle,是否可以在执行 select 语句时指出哪些行当前被锁定(哪些未被锁定)(我不想锁定任何行,只能够显示哪些行被锁定)?

例如,一个伪列将针对该行返回锁定/事务:
SELECT 锁名 FROM emp;

【问题讨论】:

  • 为什么要显示哪些行被锁定?如果目的是防止某人尝试锁定其他人已经在处理的行,则使用 SKIP LOCKED 选择未锁定的行可能更容易(取决于 Oracle 版本,这可能会或可能不会可用/记录)。
  • @OMG Ponies:没有阻塞,因此将值放入 dbms_rowid.rowid_create 从 v$session 会创建一个表中不存在的 rowid(至少这就是我猜测的原因它没有用)。 @贾斯汀洞穴:是的,这是我的意图。 SKIP LOCKED 听起来可能可行。

标签: oracle locking


【解决方案1】:

你可以做的一件事是——虽然它的效率不是很高,所以我不想将它用于大型数据集。创建一个行级函数来尝试锁定行。如果失败,则该行已被锁定

    CREATE OR REPLACE FUNCTION is_row_locked (v_rowid ROWID, table_name VARCHAR2)
   RETURN varchar2
IS
   x   NUMBER;
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
   EXECUTE IMMEDIATE    'Begin
                           Select 1 into :x from '
                              || table_name
                              || ' where rowid =:v_rowid for update nowait;
                         Exception
                            When Others Then
                              :x:=null;
                         End;'
   USING OUT x, v_rowid;

   -- now release the lock if we got it. 
   ROLLBACK;

   IF x = 1
   THEN
      RETURN 'N';
   ELSIF x IS NULL
   THEN
      RETURN 'Y';
   END IF;
END;
/

然后你可以

Select field1, field2, is_row_locked(rowid, 'MYTABLE') from mytable;

它会起作用,但它既不美观也不高效。

确实,它只有一种可取之处——即使您在链接文档中所需的各种 v$ 表上没有选择权限,它也能正常工作。但是,如果您有特权,则绝对要走另一条路。

【讨论】:

  • 我不能走另一条路,因为没有阻塞,所以我不能从 v$session 信息中创建 rowid。请求锁是找出是否有锁的唯一方法吗?我阅读的所有在线文本都表明行锁是应用于该行的事务 ID。听起来应该很容易获得:(
  • @Cwoo 是什么让您认为获得每行锁定状态这么容易?这只是您不能忘记并发系统和隔离事务的复杂性的地方之一。
  • Cwoo,请记住,通常期望用户将事务控制留给数据库,并且充其量在出现情况时做出反应。而且,对于大容量系统,数据库可能在内存中进行大量事务控制,而不是通过写入表结构来增加开销。即使我的查询确实有效,对于一个大表来说,当您进行提取然后尝试处理结果时 - 谁说锁定仍然是您确定它们时的样子?毕竟,大多数都不会存在很长时间
  • 好吧,我想这是我可能不应该尝试做的事情!
【解决方案2】:

是否可以在执行 select 语句时指出哪些行当前被锁定(哪些未被锁定)

SELECT 语句永远不会锁定任何行 - 除非您使用 FOR UPDATE 来要求它。

如果您想查看由于 SELECT ... FOR UPDATE(或实际更新)而持有的锁,您可以查询 v$lock 系统视图。

有关如何使用该视图的示例,请参阅 OMG Pony 发布的链接。

【讨论】:

    【解决方案3】:

    我认为@Michael Broughton 的回答是唯一可行的方法。这是因为 V$LOCK 并非 100% 准确。

    会话不等待一行,它们等待修改该行的事务结束。大多数情况下,这两个概念是同一个概念,但当您开始使用保存点时则不然。

    例如:

    • 会话 1 创建一个保存点并修改一行。
    • 会话 2 尝试修改相同的 行,但看到会话 1 已经有该行, 并等待会话 1 完成。
    • 会话 1 回滚到 保存点。这将删除其条目 从国际交易日志,但不结束 交易。会话 2 仍在 等待会话 1。根据 V$LOCK 会话 2 仍在等待 那一行,但这不是真的 因为现在会话 3 可以修改它 排。 (如果会话 1 执行 提交或回滚,会话 2 将 等待会话 3。)

    对不起,如果这令人困惑。您可能需要逐步浏览 OMG Ponies 提供的链接,然后使用保存点重试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 2014-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多