SQL和PL/SQL中Savepoint一事務(wù)范圍內(nèi)中間標(biāo)志經(jīng)常用于將一個(gè)長事務(wù)劃分為小部分保留點(diǎn)Savepoint可標(biāo)志長事務(wù)中任何點(diǎn)允許可回滾該點(diǎn)之后操作解決源代碼中經(jīng)常解決Savepoint;例如一過程包含幾個(gè)函數(shù)每個(gè)函數(shù)前可建立一個(gè)保留點(diǎn)如果函數(shù)失敗很容易返回到每一個(gè)函數(shù)開始情況回滾到一個(gè)Savepoint之后該Savepoint之后所獲得數(shù)據(jù)封鎖被釋放為了處理方案部分回滾可以用帶TO Savepoint子句ROLLBACK語句將事務(wù)回滾到指定位置
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序制作、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了文安免費(fèi)建站歡迎大家使用!
例
BEGIN
INSERT INTO ATM_LOG(whowhenwhatwhere)
VALUES ('Kiesha'SYSDATE'Withdrawal of $100''ATM54')
SAVEPOINT ATM_LOGGED;
UPDATE checking
SET balance=balance-100
RETURN balance INTO new_balance;
IF new_balance0
THEN
ROLLBACK TO ATM_LOGGED;
COMMIT
RAISE insufficient_funda;
END IF
END
關(guān)鍵字SAVEPOINT可選所以下面兩個(gè)語句等價(jià):
ROLLBACK TO ATM_LOGGED;
ROLLBACK TO SAVEPOINT ATM_LOGGED;
在沒有做過commit或者其他會導(dǎo)致隱式提交的語句之前(如DDl語言), 可以執(zhí)行rollback.
提交過只能用閃回或者從備份中恢復(fù)了
oracle使用語句savepoint sp_begintran開啟顯式事務(wù),鎖本身和事務(wù)是沒有關(guān)系的,只要是數(shù)據(jù)庫的操作都會產(chǎn)生鎖。處于事務(wù)中的SQL語句只有這個(gè)事務(wù)提交(commit)之后,事務(wù)中的SQL語句影響的表記錄上的鎖才會釋放。鎖常見有共享鎖(select語句產(chǎn)生)和排它鎖(DML語句產(chǎn)生),如果一個(gè)表上加載有共享鎖,還可以疊加共享鎖,但不能疊加排它鎖。如果一個(gè)表上加載有排他鎖,就什么鎖都不能加了,也就是說如果DML語句占用過多的時(shí)間,這些數(shù)據(jù)庫效率就不高,就需要優(yōu)化,當(dāng)然select語句性能低了也不行。
每個(gè)存儲過程可以不用顯式事務(wù),它本身就為你開啟了一個(gè)隱式事務(wù),如果需要開啟顯示事務(wù),就通過savepoint sp_begintran開啟,無論是不是顯式還是隱式事務(wù),你都得通過commit work提交事務(wù),通過exception捕捉SQL語句異常,在異常發(fā)生時(shí)需要回滾事務(wù)(rollback work)。
學(xué)習(xí)存儲過程中使用斷點(diǎn)回滾事務(wù)時(shí),發(fā)現(xiàn)目前網(wǎng)絡(luò)上存在一個(gè)問題,那就是使用斷點(diǎn)回滾后,都忘記了一個(gè)很重要的事情,提交事務(wù)。雖然使用了斷點(diǎn)回滾,但是斷點(diǎn)回滾不像rollBack或commit一樣結(jié)束當(dāng)前事務(wù),而使用斷點(diǎn)回滾只會回滾到聲明斷點(diǎn)的地方,之前的產(chǎn)生的事務(wù)仍需要提交的,如果不提交,事務(wù)一直在數(shù)據(jù)庫中緩存.
Demo:
procedure doSomeThing(p_number out number) as
begin
insert into t_test_user_mingming(id,loginname,password,realname,type)
values(se_test_user_mingming_id.nextval,'xiaoming','1234','小明',1);
p_number := 1;
savepoint ps;--- 設(shè)置斷點(diǎn) ps
insert into t_test_info_mingming(id,pal,type,create_time,note)
values(se_test_info_id.nextval,'我想買臺thinkPad 可以俺莫有錢',1,sysdate,'ceshi');
p_number := 2;
savepoint sp;----設(shè)置斷點(diǎn) sp
insert into t_test_agent(agent_id) values(1);---我這里此行會拋出異常 ORA-01400 可以替換為下句 手動拋出一個(gè)異常
-----RAISE_APPLICATION_ERROR (-20004,'拋出的異常玩玩');
commit;
exception --捕獲異常
when others then
rollback to ps; ---- 如果產(chǎn)生異常,回滾到斷點(diǎn) ps
p_number :=0;
commit; --- 提交事務(wù)
end doSomeThing;
這里本人做了實(shí)驗(yàn),如果在異常中不加 commit 語句,使用PL/SQL測試時(shí),異常在緩存,t_test_user_mingming 表中沒有數(shù)據(jù)記錄。
存儲過程里的事務(wù)操作:
create or replace procedure pr_mypro2(p_a in varchar2,p_b in varchar2,p_count out number)
temp varchar2(1000); /*定義臨時(shí)變量*/
is
begin
select code into p_count from table1 where a=p_a; /*查詢并返回值*/
temp := p_count; /*將返回值賦給臨時(shí)變量*/
savepoint point1; /*保存點(diǎn)*/
insert into table2(a,b)values(temp,p_b); /*將臨時(shí)變量值添加到新表的字段*/
savepoint point2;
insert into
exception
when others then
rollback to savepoint point1; /*異常處理,保存點(diǎn)下面的操作都不會被執(zhí)行*/
return;
end;
保存點(diǎn)(SAVEPOINT)是事務(wù)處理過程中的一個(gè)標(biāo)志,與回滾命令(ROLLBACK)結(jié)合使用,主要的用途是允許用戶將某一段處理回滾而不必回滾整個(gè)事務(wù)。
如果定義了多個(gè)savepoint,當(dāng)指定回滾到某個(gè)savepoint時(shí),那么回滾操作將回滾這個(gè)savepoint后面的所有操作(即使后面可能標(biāo)記了N個(gè)savepoint)。
例如,在一段處理中定義了五個(gè)savepoint,從第三個(gè)savepoint回滾,后面的第四、第五個(gè)標(biāo)記的操作都將被回滾,如果不使用ROLLBACK TO savepoint_name而使用ROLLBACK,將會滾整個(gè)事務(wù)處理。