sql - Oracle select for update behaviour -


the problem try solve looks this.

  • we have table full of rows represent cards. purpose of reservation transaction assign card client
  • a card can not belong many clients
  • after time (if not bought) card has returned pool of available resurces
  • reservation can done many clients @ same time
  • we use oracle database storing data, solution has work @ least on oracle 11

our solution assign status card, , store it's reservation date. when reserving card using "select update" statement. query looks available cards , cards reserved long time ago.

however our query doesn't work expected.

i have prepared simplified situation explain problem. have card_numbers table, full of data - of rows have non-null id numbers. now, let's try lock of them.

-- first, in session 1 set autocommit off;  select id card_numbers   id not null   , rownum <= 1   update skip locked; 

we don't commit transaction here, row has locked.

-- later, in session 2 set autocommit off;  select id card_numbers   id not null   , rownum <= 1   update skip locked; 

the expected behaviour in both sessions single, different row satisfies query conditions.

however doesn't work way. depending on whether use "skip locked" part of query or not - behavious changes:

  • without "skip locked" - second session blocked - waiting transaction commit or rollback in session one
  • with "skip locked" - second query returns empty result set

so, after long introduction comes question.

is kind of desired locking behaviour possible in oracle? if yes, doing wrong? correct solution?

the behaviour you've encountered for update skip locked has been described in this blog note. understanding update clause evaluated after clause. skip locked additional filter guarantees among rows have been returned, none locked.

your statement logically equivalent to: find first row card_numbers , return if not locked. not want.

here little test case reproduces behaviour describe:

sql> create table t (id primary key)   2  select rownum dual connect level <= 1000;  table created  session1> select id t rownum <= 1 update skip locked;          id ----------          1  session2> select id t rownum <= 1 update skip locked;          id ---------- 

no row returned second select. can use cursor work around issue:

sql> create function get_and_lock return number   2     cursor c select id t update skip locked;   3     l_id number;   4  begin   5     open c;   6     fetch c l_id;   7     close c;   8     return l_id;   9  end;  10  /  function created  session1> variable x number; session1> exec :x := get_and_lock;  pl/sql procedure completed x --------- 1  session2> variable x number; session2> exec :x := get_and_lock;  pl/sql procedure completed x --------- 2 

since i've explicitely fetched cursor, 1 row returned (and 1 row locked).


Comments

Popular posts from this blog

objective c - Change font of selected text in UITextView -

php - Accessing POST data in Facebook cavas app -

c# - Getting control value when switching a view as part of a multiview -