我有一个使用 Oracle 数据库的 C# 应用程序。我需要一个查询来从 oracle 数据库中的表中获取未锁定的行。如何选择所有未锁定的行?
是否有任何“翻译器”可以将此 T-SQL(MS SQL Server)查询翻译成 Oracle 方言?
SELECT TOP 1 * FROM TableXY WITH(UPDLOCK, READPAST);
我对 Oracle 缺少这样的功能有点失望。他们想让我使用 AQ 还是什么?
Oracle 确实有这个特性,特别是SELECT 语句的 SKIP LOCKED 部分。去引用:
SKIP LOCKED 是处理锁定某些感兴趣行的竞争事务的另一种方法。指定 SKIP LOCKED 以指示数据库尝试锁定 WHERE 子句指定的行并跳过发现已被另一个事务锁定的任何行。
文档继续说它是为在多消费者队列中使用而设计的,但这并不意味着您必须在这种环境中使用它。尽管文档说这是有一个很大的警告。您不能要求接下来的 N 行解锁 - 只有接下来的 N 行,其中解锁的行将被返回。
SELECT *
FROM TableXY
WHERE ROWNUM = 1
FOR UPDATE SKIP LOCKED
请注意,如果您选择的表被锁定为独占模式,即您已经指示数据库不要让任何其他会话锁定该表,那么在释放独占锁之前您将不会获得任何返回的行。
我最近遇到了同样的问题,在解决之后,我写了这篇博文:
http://nhisawesome.blogspot.com/2013/01/how-to-lock-first-unlocked-row-in-table.html
欢迎发表评论!感谢您的意见。
简短的总结:我选择了一堆记录,而不是选择第一个解锁的记录并锁定它,然后循环遍历这些记录并尝试使用 SKIP LOCKED 提示获取对它的锁定。如果所选的一个不可锁定,则继续进行下一个,直到获得锁定或没有锁定。
如果您选择锁定的行,select for update nowait 将出错。那是你要的吗?我很好奇您要解决什么问题。除非您有长时间运行的事务,否则行上的锁从一个时刻到下一个时刻都是短暂的。
例子:
创建表测试(COL1 NUMBER(10) NOT NULL,COL2 VARCHAR2(20 BYTE) NOT NULL);
CREATE UNIQUE INDEX TEST_PK ON TEST (COL1);
ALTER TABLE TEST ADD (CONSTRAINT TEST_PK PRIMARY KEY (COL1) USING INDEX TEST_PK);
SQL 会话 #1: SQL> 插入测试值(1,'1111'); 创建了 1 行。SQL> 插入测试值(2,'2222'); 创建了 1 行。SQL>提交;提交完成。SQL> 更新测试集 col2='AAAA' where col1=1; 更新了 1 行。
SQL 会话 #2:尝试读取锁定的行,得到错误:
SQL> select * from test where col1=1 for update nowait; select * from test where col1=1 for update nowait * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired