使用 "Optimistic locking" 的问题 我无法在查看 table 后更新

Problem with using "Optimistic locking" I can not update after viewing the table

我在 table 中添加了 tcn:

alter table accounts add TCN integer;

UPDATE accounts set TCN = DBMS_UTILITY.GET_TIME;

并且tcn不能为空alter table accounts modify TCN not null;

我在更新前创建了触发器

SQL> create or replace trigger acc_preupdate
  2  before update on accounts
  3  for each row
  4  begin
  5  if(:NEW.TCN != :OLD.TCN+1) THEN
  6  RAISE_APPLICATION_ERROR(-20000, 'Concurrency Failure');
  7  end if;
  8  :NEW.TCN := DBMS_UTILITY.GET_TIME;
  9  END;
 10  /

并在插入前触发

SQL> create or replace trigger acc_preinsert
  2  before insert on accounts
  3  for each row
  4  begin
  5  :NEW.TCN := DBMS_UTILITY.GET_TIME;
  6  end;
  7  /

我插入table

SQL> insert into accounts (acc_id, acc_name, acc_amount, acc_date)
  2  values(acc_seq.nextval, 'petar', 15000, sysdate);

当我想更新 table 时,出现了这个错误

SQL> update accounts
  2  set acc_amount = 1000000
  3  where acc_id = 1;
update accounts
       *
ERROR at line 1:
ORA-20000: Concurrency Failure
ORA-06512: at "PETAR1.ACC_PREUPDATE", line 3
ORA-04088: error during execution of trigger 'PETAR1.ACC_PREUPDATE'

现在我 select id 为 1 的用户。

select acc_name, acc_amount from accounts where acc_id = 1;

当我再次尝试更新 table 时,我得到了同样的错误。

为什么我不能更新table?

我使用 Oracle 12c r2

在最后的 update 语句中,您没有指定对 TCN 的更新,因此在 update 触发器中,:OLD.TCN 的值就是您插入的值之前(通过 insert 触发器)。由于 update 没有明确更改它,因此 :NEW.TCN 也是相同的值。

因此 :OLD.TCN 等于 :NEW.TCN 并使 update 触发器中的 if 条件为真,引发您的自定义异常。