Oracle SELECT FOR UPDATE - Demonstration?

南笙酒味 提交于 2021-02-10 14:23:09

问题


I am quite not understanding the lock functionality with SELECT FOR UPDATE.

Here is what I've tried.

CREATE TABLE ACCOUNT_TAB (
  ACC_ID int NOT NULL PRIMARY KEY,
  BALANCE int NOT NULL
);

INSERT INTO ACCOUNT_TAB
VALUES(1, 100);

SELECT * FROM ACCOUNT_TAB FOR UPDATE; 
SELECT * FROM ACCOUNT_TAB; 

Both SELECT will retrieve the row, but shouldn't the first query lock the row in the ACCOUNT_TAB table?

I have read something about sessions: queries from the same session don't care about the lock. Can I somehow in a single script file demonstrate the lock function? For example, can I run two different sessions in one script so the second call will retrieve an error saying that the row is locked?


回答1:


Your original experiment failed to demonstrate the locking because in Oracle writes don't block reads. The FOR UPDATE clause allows us to avoid situations in which two sessions attempt to write to the same record; any number of sessions can read a record.

"Okay but still, is there some way to demonstrate the lock in a single script file?"

Yes. Here is a script with a local procedure which uses the autonomous_transaction pragma to simulate a multi-user environment:

declare
    procedure p1 (p_id in number) is
        pragma autonomous_transaction;
        cursor c23  is
            select * from t23
            where id = p_id
            for update nowait;
        r23 c23%rowtype;
    begin
        dbms_output.put_line('nested transaction');
        open c23;
        fetch c23 into r23;
        update t23 
        set col2 = col2 * 2;
        close c23;
        commit;
    exception
        when others then
            dbms_output.put_line(sqlerrm);
    end;

begin
    update t23
    set col1 = 2
    where id = 1;

    p1 (1);

    commit;
end;
/

The first UPDATE statement issues a lock, which causes the procedural call to fail because it can't get a lock (due to use of NOWAIT clause):

  ...
  30  end;
  31  /
nested transaction
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

PL/SQL procedure successfully completed.

SQL> 



回答2:


RDBMS will obtain exclusive row-level locks on all rows identified by SELECT FOR UPDATE statement, so only you are the only one allowed to update them. It means that other RDBMS client won't be able to alter any of this records until you perform either a COMMIT or a ROLLBACK. So if you want to test how exactly it works, create two separate client connections and try first to lock record in one session, and then try to update same record in another one.



来源:https://stackoverflow.com/questions/44865703/oracle-select-for-update-demonstration

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