savepoint是事務內部允許部分rollback的標志符。因為事務中對記錄做了修改,我們可以在事務中創建savepoint來標識不同的點。如果遇到錯誤,就可以rollback到不同的點或直接回來事務最開始的點。
SAVEPOINT和ROLLBACK TO SAVEPOINT語法:
SAVEPOINT identifier
ROLLBACK [WORK] TO SAVEPOINT identifier
RELEASE SAVEPOINT identifier
例子:
create table t(id number,name varchar2(10));
//創建savepoint t1
insert into t values (1,'Tough1');
savepoint t1;//創建savepoint t2
insert into t values (2,'Tough2');
savepoint t2;//創建savepoint t3
update t set name='Tough' where id=2;
savepoint t3;//回滾到update之前的狀態,savepoint t3丟失
rollback to savepoint t2;//回到第一個insert之前的狀態,即空表。
rollback;//如果執行COMMIT,當前事務的所有保存點被刪除
commit;delete from t where id=1;
savepoint t4;//COMMIT后,當前事務的所有保存點被刪除。rollback時出現錯誤。
//ORA-01086: 從未創建保存點 'T3'
rollback to savepoint t3;
Savepoints在應用程序中同樣有用。如果一個過程包含幾個函數,那可以在每個函數前創建一個savepoint。如果一個函數失敗,返回數據到函數開始前的狀態並在修改參數或執行一個恢復操作后重新運行函數就非常容易。
在回滾到一個savepoint后,Oracle釋放由被回滾的語句持有的鎖。其他等待之前被鎖資源的事務可以進行了。其他要更新之前被鎖行的事務也可以執行。
當一個事務回滾到一個savepoint,發生下列事件:
1. Oracle僅回滾savepoint之后的語句。
2. Oracle保留這一savepoint,但所有建立於此后的savepoints丟失。
3. Oracle釋放在該savepoint后獲得的所有表、行鎖,但保留之前獲得的所有鎖。
4. 事務保持活動並可繼續。
無論何時一個會話在等待事務,到savepoint的回滾不會釋放行鎖。為了確保事務如果無法獲得鎖也不會懸掛(hang),在執行UPDATE或DELETE前使用FOR UPDATE ... NOWAIT。(這里指回滾的savepoint之前獲得的鎖。該savepoint后獲得的行鎖會被釋放,之后執行的語句也會被徹底回滾。)
如果執行COMMIT,當前事務的所有保存點被刪除。rollback時出現錯誤-ORA-01086: 從未創建保存點 'T3'。