显示 Oracle 中锁定的行

发布于 2024-10-20 03:51:23 字数 128 浏览 5 评论 0原文

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

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

Using Oracle, is it possible to indicate which rows are currently locked (and which are not) when performing a select statement (I don't want to lock any rows, just be able to display which are locked)?

For example, a pseudo column that would return the lock/transaction against the row:
SELECT lockname FROM emp;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时间海 2024-10-27 03:51:23

你可以做的一件事是这样 - 尽管它不是非常有效,所以我不想将它用于大型数据集。创建一个行级函数来尝试锁定该行。如果失败,则该行已经被锁定

    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$ 表的选择权限,它也能工作。不过,如果你有特权,一定要走另一条路。

One thing you could do is this - although it is not terribly efficient and so I wouldn't want to do use it for large data sets. Create a row-level function to try and lock the row. If it fails, then the row is already locked

    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;
/

And then you could

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

It will work, but it isn't pretty nor efficient.

Indeed, it has exactly one redeeming quality - it will work even if you don't have select privs on the various v$ tables required in the linked document. If you have the privs, though, definitely go the other route.

撩动你心 2024-10-27 03:51:23

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

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

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

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

is it possible to indicate which rows are currently locked (and which are not) when performing a select statement

A SELECT statement will never lock any rows - unless you ask it to by using FOR UPDATE.

If you want to see locks that are held due to a SELECT ... FOR UPDATE (or a real update), you can query the v$lock system view.

See the link that OMG Pony posted for an example on how to use that view.

最佳男配角 2024-10-27 03:51:23

我认为@Michael Broughton 的答案是唯一永远有效的方法。这是因为 V$LOCK 并不是 100% 准确的。

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

例如:

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

抱歉,如果这令人困惑。您可能需要单步执行 OMG Ponies 提供的链接,然后使用保存点重试。

I think @Michael Broughton's answer is the only way that will always work. This is because V$LOCK is not accurate 100% of the time.

Sessions don't wait for a row, they wait for the end of the transaction that modified that row. Most of the time those two concepts are the same thing, but not when you start using savepoints.

For example:

  • Session 1 creates a savepoint and modifies a row.
  • Session 2 tries to modify that same
    row, but sees session 1 already has that row,
    and waits for session 1 to finish.
  • Session 1 rolls back to the
    savepoint. This removes its entry
    from the ITL but does not end the
    transaction. Session 2 is still
    waiting on session 1. According to
    V$LOCK session 2 is still waiting on
    that row, but that's not really true
    because now session 3 can modify that
    row. (And if session 1 executes a
    commit or rollback, session 2 will
    wait on session 3.)

Sorry if that's confusing. You may want to step through the link provided by OMG Ponies, and then try it again with savepoints.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文