Skip to main content
added 25 characters in body
Source Link
András Váczi
  • 31.6k
  • 13
  • 101
  • 149

X NAME Version_Number

1 john 1

X   NAME   Version_Number

1   john   1

2   mary   2

2 mary 2.

X NAME Version_Number

1 john 1

2 mary 2

X   NAME   Version_Number

1   john   1

2   mary   2

.

Source Link

Alas, the ora_rowscn approach is not going to work very well. It still enables "lost updates".

I have my information from AskTom: ORA_ROWSCN for optimistic locking

Copied example here to anticipate dead links...

set echo on

drop table t;
create table t ( x int primary key, name varchar2(30) ) rowdependencies;

insert into t values ( 1, 'john' );
insert into t values ( 2, 'mary' );
commit;

variable ora_rowscn number
set autoprint on
exec select ora_rowscn into :ora_rowscn from t where x = 2;

set echo off
prompt in another session issue:
prompt variable ora_rowscn number
prompt set autoprint on
prompt exec select ora_rowscn into :ora_rowscn from t where x = 2;;
prompt and come back here and hit enter...
pause

set echo on
update t set name = 'beth' where x = 2 and ora_rowscn = :ora_rowscn;

set echo off
prompt in another session issue:
prompt update t set name = 'sally' where x = 2 and ora_rowscn = :ora_rowscn;;
prompt and come back here and hit enter...
pause

commit;

set echo off
prompt now commit in the other session and notice your lost update :(

What you should do IMHO, is to add an extra column (eg: Version_Number) to your table where you set the nextval of a sequence on update of a record (using a trigger, or do this in the package code).

WorkFlow: Client queries some rows and obtains the data with the version_Number. When updating this data he needs to check the version_number with the current version_number in the record. If they differ, no row will be updated and you should return an error to the client (No_Records_Found).

create table t ( x int primary key, name varchar2(30), version_Number number);
create sequence s_t start with 1 increment by 1;

insert into t values ( 1, 'john', s_t.nextval);
insert into t values ( 2, 'mary', s_t.nextval);
commit;

select * from t;

You see something like this:

X NAME Version_Number

1 john 1

2 mary 2

-- first session
update t set name = 'beth', version_number = s_t.nextval where x = 2 and version_number = 2;

-- second session
update t set name = 'sally', version_number = s_t.nextval where x = 2 and version_number = 2; 

-- First session
commit;

-- Second session returns with no updated records...

As I said, you should notify the client that there was no record updated, but this could have 2 reasons:

  • outdated record
  • deleted record

In both cases the client has to refresh this record again and determine what to do next.