MySQL 中使用 start transaction 和 rollback 能夠進行事務操做,將多個更新操做打包爲一個原子性操做。但當遇到事務內細粒度的控制時,就顯得比較無力了。所以,MySQL 提供了單個事務內經過標記來進行更細粒度控制的語句。code
就像遊戲中的存儲節點同樣,咱們能夠經過如下語句來在一個開啓的事務內聲明標記一個存儲點,以便爲事務內部分回滾操做提供標記:遊戲
savepoint point_name;
該語句在事務內插入了一個標記位,當遇到回滾到指定存儲點的命令且二者之間未進行提交操做時,將撤銷二者間的所有數據更新操做。事務
當須要進行事務內部分操做的回滾時,可使用如下語句:it
rollback to savepoint point_name;
該語句將撤銷從當前語句追溯至對應 savepoint 聲明處所有未提交的數據更新操做。若是部分回滾語句前有 提交語句或所有回滾的語句出現,將會完成當前事務,此時若執行部分回滾將會提示 "SAVEPOINT point_name does not exist" 的錯誤。io
當確認存儲點語句再也不須要部分回滾的操做後,可執行如下語句解除指定的存儲點:table
release savepoint point_name;
執行了解除語句後該存儲點將再也不可用,沒法再執行對應的部分回滾語句,不然將會提示 "SAVEPOINT point_name does not exist" 的錯誤。打包
一個事務內能夠存在多個 savepoint,以此來將一個大的事務劃分紅多個小的內嵌可回滾的事務代碼塊或代碼層次,如:數據
start transaction; insert into table1 values('a1', 'b1'); savepoint p1; insert into table1 values('a2', 'b2'); rollback to savepoint p1; savepoint p2; insert into table1 values('a3', 'b3'); rollback to savepoint p2; commit;
或者tab
start transaction; insert into table1 values('a1', 'b1'); savepoint p1; insert into table1 values('a2', 'b2'); savepoint p2; insert into table1 values('a3', 'b3'); rollback to savepoint p2; rollback to savepoint p1; commit;
但多個事務塊不能造成交叉,如:poi
start transaction; insert into table1 values('a1', 'b1'); savepoint p1; insert into table1 values('a2', 'b2'); savepoint p2; insert into table1 values('a3', 'b3'); rollback to savepoint p1; rollback to savepoint p2; commit;
不然將致使先回滾的代碼 p1 事務塊撤銷了其中的 p2 存儲點的聲明語句,而致使 p2 事務塊回滾時提示 "SAVEPOINT p2 does not exist" 的錯誤。