Select unlocked rows oracle

不问归期 提交于 2019-12-08 13:22:36

问题


I have an application in C# that uses an Oracle database. I need a query to fetch the unlocked row from a table in oracle database. How can I select all unlocked rows?

Is there any 'translator' out there that can translate this T-SQL (MS SQL Server) query to Oracle dialect?

SELECT TOP 1 * FROM TableXY WITH(UPDLOCK, READPAST);

I'm a little bit disappointed with Oracle lacking such a feature. They want to make me use AQ or what?


回答1:


Oracle does have this feature, specifically the SKIP LOCKED portion of the SELECT statement. To quote:

SKIP LOCKED is an alternative way to handle a contending transaction that is locking some rows of interest. Specify SKIP LOCKED to instruct the database to attempt to lock the rows specified by the WHERE clause and to skip any rows that are found to be already locked by another transaction.

The documentation goes on to say it's designed for use in multi-consumer queues but this does not mean that you have to use it in this environment. Though the documentation says this there is a large caveat. You can't ask for the next N unlocked rows - only the next N rows, of which the unlocked ones will be returned.

SELECT * 
  FROM TableXY 
 WHERE ROWNUM = 1
   FOR UPDATE SKIP LOCKED

Note that if the table you're selecting from is locked in exclusive mode, i.e. you've already instructed the database not to let any other session lock the table you will not get any rows returned until the exclusive lock is released.




回答2:


I faced with the same problem recently, and after solved it, I wrote this blog entry:

http://nhisawesome.blogspot.com/2013/01/how-to-lock-first-unlocked-row-in-table.html

Feel free to leave a comment! Your comments are appreciated.

Short summary: instead of select first unlocked one and lock it, I select a bunch of records, then loop through the bunch and try to acquire a lock on it using SKIP LOCKED hint. If the selected one is not lockable, move on to the next one, until a lock acquired or none remain.




回答3:


select for update nowait will error out if you select a row that is locked. Is that what you want? I am curious as to what problem you are trying to solve. Unless you have long-running transactions, the lock on a row would be transient from one moment to the next.

Example:

CREATE TABLE TEST ( 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 Session #1: SQL> insert into test values(1,'1111'); 1 row created. SQL> insert into test values(2,'2222'); 1 row created. SQL> commit; Commit complete. SQL> update test set col2='AAAA' where col1=1; 1 row updated.

SQL Session #2: Attempt to read locked row, get error:

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



来源:https://stackoverflow.com/questions/14113744/select-unlocked-rows-oracle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!