MySQL支持的幾種數據庫引擎,並非所有的引擎都支持明確的事務處理管理,MYISAM 和 INNODB 是最常用的引擎,而MYISAM 不支持事務處理,innodb支持事務處理,所以一定要正確 使用引擎類型。
事務處理(transaction processing):可以用來維護數據庫的完整性,保證成批的MySQL操作要么完全執行,要么完全不執行。
事務(transaction): 指將一系列數據操作捆綁成一個整體進行統一管理。如果某一事務執行成功,則在該事務中進行的所有數據更改都會提交,成為數據庫中永久組成部分。如果事務執行時遇到錯誤且必須取消或回滾,則所有數據將全部恢復到操作前的狀態,所有數據的更改均被清除。
在銀行業務中有一個記賬原則,有借有貸,借貸相等,大致意思就是,當一筆轉賬業務在進行時,兩方之間的總額在轉賬前后還是一致的。因此就需要事務來進行管理,不能我這邊減少了,中間發生錯誤對方沒收到,帳就這么對不上了。
事務是一種機制、一個操作序列,包含了一組數據庫操作命令,並且把所有的命令作為一個整體一起向系統提交或撤銷操作請求,要么全都執行成功, 要么全都不執行。因此事務是一個不可分割的工作邏輯單元。
在數據庫系統上執行並發操作時,事務是作為最小的控制單元來進行使用,特別適用於多用戶同時操作的數據庫系統。如:訂票、銀行、證券交易等系統
一、四大特性
事務作為一個邏輯工作單元,主要有四個屬性:原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)通常放到一塊簡稱為ACID
(1)、原子性
事務是一個完整的操作,事務的個元素是不可分的(原子的)。事務中的所有元素必須作為一個整體提交或回滾,如果事務中的任何元素失敗,則整個事務都將失敗。
如:A 給 B 轉賬,A若轉賬成功,B 就收到,否則,轉賬失敗
(2)、一致性
當事務完成時,數據必須處於一致狀態。也就是說在事務開始之前數據庫中存儲的數據處於一致狀態。在正在進行的事務中,數據可能處於不一致狀態(如:數據被修改),但當事務完成時,數據必須再次回到已知的一致狀態。通過事務對數據所做的修改不能損壞數據,或者說事務不能使數據存儲處於不穩定的狀態。
如: A 給 B 轉賬,轉賬前兩者總額處於一致狀態,在進行轉賬時若A 修改了,B也修改了,此時二者總額與之前一致,則處於一致狀態,若A改了,B未改,二者總額與之前不一致則處於不一致狀態。
(3)、隔離性
對數據進行修改的所有並發事務是彼此隔離的,這表明事務是必須獨立的,它不應以任何方式依賴於或影響其他事務。修改數據的事務可以在另一個使用相同數據的事務開始之前訪問這些數據,或者在另一個使用相同數據的事務結束之后訪問這些數據,另外,當事務修改數據時,如果任何其他進程正在同時使用相同的數據,則直到該事務成功提交之后,對數據的修改才能生效。
如:A與B之間轉賬,C與D之間轉賬,永遠是相互獨立。
(4)、持久性
指不管系統是否發生了故障,事務處理的結果都是永久的。
一個事務成功執行完成之后,它對於數據庫的改變是永久性的,即使系統出現故障也是如此,也就是一旦事務被提交,事務的效果會被永久地保留在數據庫中。
二、執行事務
任何一種數據庫都會擁有各種各樣地日志,用來記錄數據地運行情況、日常操作、錯誤信息等,MySQL也不列外。如:當用戶root 登錄到MySQL服務器,就會在日志文件里記錄該用戶的登錄時間、執行操作等,為了維護Mysql服務器經常需要在MySQL數據庫中進行日志操作
MySQL中支持事務地存儲引擎有InnoDB 和 BDB,InnoDB存儲引擎管理事務主要通過UNDO日志和REDO 日志實現。
UNDO日志:復制事務執行前的數據,用於在事務發生異常時回滾數據。
REDO日志:記錄在事務執行中,對數據進行的每條更新操作,當事務提交時,該內容將被刷新到磁盤。
默認設置下,每條SQL就是一個事務,即執行SQL語句后自動提交。為了達到將幾個操作作為一個整體的目的,需要使用 BEGIN 和 START TRANSACTION 開啟一個事務,或執行命令 SET AUTOCOMMIT = 0,來禁止當前會話的自動提交,命令后面的語句作為事務的開始。
One、在使用事務和事務處理時常用的關鍵字
事務(transaction)指一組SQL語句
回退(rollback)指撤銷指定SQL語句的過程
提交(commit)指將未存儲的SQL語句結果寫入數據表
保留點(savepoint)指事務處理中設置的臨時占位符(placeholder),你可以對它發布回退(與回退整個事務處理不同)
注意:當commit 或 rollback 語句執行后,事務會自動關閉
Two、開啟事務
管理事務處理的關鍵在於將sql語句組分解成邏輯塊,並確定規定數據何時應該回退,何時不應該回退。
-- 標識事務的開始 start transaction 或 begin
這個語句顯示地標記一個事務地起始點。
Three、使用 ROLLBACK(回退:用來管理insert 、update、delete 語句)
ROLLBACK 只能在一個事務處理內使用,也就是在執行了一條start transaction之后,將start transaction 之后的所有語句回退。
-- 開啟事務 start transaction; -- 在事務中刪除 ordertotals delete from ordertotals; -- 查看一下還有沒 select * from ordertotals; -- 回退,反悔了不能刪除 rollback;
rollback 清楚自事務起始點至該語句所做地所有數據更新操作,將數據狀態回滾到事務開始前,並釋放由事務控制地資源。
上述,首先查詢不為空的一個表,然后開啟了一個事務處理,用一條delete語句刪除這個表中的所有行,驗證一下是否空了,這時用一條回退(rollback)語句,將start transaction 之后的所有語句回退,最后驗證一下是否成功。
注意:
事務處理ROLLBACK用來管理insert 、update、delete 語句,不能回退Crete、drop、select操作(雖然可以執行但是沒用)。
Four、使用COMMIT(提交)
一般的MySQL語句都是直接針對數據表執行和編寫的。這就是所謂的隱含提交(implicit commit),即提交(也可以叫寫、保存)操作是自動進行的。
注意:在事務處理塊中,提交不會隱含地進行,為了進行明確的提交,要使用commit 語句。
-- 從數據庫中刪除訂單號為 20007的訂單,注意要先刪除明細在刪除訂單,不然由於主外鍵的關系導致刪除不了 -- 開啟事務 start transaction; -- 刪除明細表中 delete from orderitems where order_num = 20007; -- 刪除訂單表中 delete from orders where order_num = 20007; -- 提交 commit;
commit 標志一個事務成功提交,自事務開始至提交語句之間執行的所有數據更新將永久地保存在數據庫文件中,並釋放連接時占用地資源。
上述中,從數據庫中完全刪除訂單20010.,主要涉及更新兩個數據表orders 和 orderitems,所以使用事務處理塊來保證訂單不被部分刪除,最后使用commit 語句僅在不出錯時寫出更改,如果第一條刪除語句起作用,但第二條失敗,則delete語句不會被提交(而會被自動撤銷)
Five、使用保留點(savepoint)
簡單的rollback 和commit 語句就可以寫入或撤銷整個事務處理,但是更復雜事務處理可能會部分提交或回退,所以引入了保留點
如之前的添加訂單場景,如果發生錯誤回退到 添加 orders 行之前就行,不需要回退到客戶表
為了支持回退部分事務處理,必須能在事務處理塊中合適的位置防止占位符,這樣如果需要回退,就可以回退到某個占位符。而這些占位符就稱為保留點(創建時可以使用 savepoint 聲明)
-- 創建保留點 savepoint 保留點名 -- 回退到保留點 rollback to 保留點名
注意:
1、每個保留點的名字必須要唯一而且要有意義,以便在回退時,MySQL知道回到哪
2、可以設置任意多的保留點,而且時越多越好,因為保留點越多,就越可以靈活的進行回退
3、保留點在事務處理完成(即執行一條Rollback或commit )之后自動釋放,在MySQL 5 后也可以用RELEASE SAVEPOINT 明確的釋放保留點。
Six、更改默認的提交 (autocommit)
默認的MySQL行為時自動提交所有更改,也就是任何時候執行一條MySQL語句,該語句對表的更改時立即執行生效的。如果要想關閉可以使用以下語句;
-- 關閉默認提交 set autocommit = 0;
注意:
1、autocommit 決定是否自動提交更改,不管有沒有commit 語句,設置autocommit 為 0(假)指示MySQL不自動提交更改,直到autocommit設置為真時為止。
2、autocommit 標志是針對每個連接而不是服務器。
三、編輯事務時要遵守以下原則
(1)、事務盡可能簡短。
事務啟動至結束在數據庫管理系統中會保留大量資源,以保證事務地原子性、一致性、隔離性和持久性。如果在多用戶系統中,較大地事務將會占用系統大量地資源,使系統不堪重負、會影響軟件地運行性能,甚至導致系統崩潰。
(2)、事務中訪問地數據量盡量最少。
當並發執行事務處理時,事務操作地數據量越少,事務之間對操作數據地爭奪就越少。
(3)、查詢數據時不要使用事務。
對數據進行瀏覽查詢操作並不會更新數據庫地數據,因此不使用事務查詢數據,以避免占用過量地系統資源。
(4)、在事務處理過程中盡量不要出現等待用戶輸入地操作。
在處理事務地過程中,如果需要等待用戶輸入數據,那么事務會長時間地占用資源,有可能造成系統阻塞。
end!!!!!
在關系型數據庫設計把數據存儲在多個表中,使數據更容易操縱、維護和重用。
如:訂單存儲在orders 表和orderitems 表中,order存儲實際的訂單,而orderitems 存儲訂購的各項物品,這兩個表使用主鍵相互關聯,又包含客戶和產品信息的其他表相關聯
給系統添加訂單的過程如下
1、檢查數據庫中是否存在相應的客戶(從customer 表中查詢),如果不存在添加他/她
2、檢索客戶的ID
3、添加一行到orders 表,把它與客戶ID關聯
4、檢索orders表中賦予的新的訂單ID
5、對於訂購的每個物品在orderitems 表中添加一行,通過檢索出來的ID 把它與orders表關聯(以及通過產品ID 與product表關聯)
從中可以看出,一個添加訂單的過程涉及的客戶表,訂單表,訂單明細表,產品表(要是復雜一點可能還涉及到物流配送,庫存占用)
如果要是數據庫發生了某種故障(如超出磁盤空間,安全限制,表鎖等)阻止了這個過程的完成。
如果故障發生在添加了客戶之后,orders 表添加之前,不會有什么問題。某些客戶沒有訂單是完全合法的。在重新執行此過程時,所插入的客戶將被檢索和使用,可以有效地從出故障的地方開始執行此過程。
如果故障發生在order行添加之后,orderitems行添加之前,會導致數據庫中有一個空的訂單
如果故障發生在系統在給orderitems添加行時,會導致數據庫出現一個不完整訂單而且你還不知道。
如何解決,這個時候事務處理就發揮作用了,事務處理是一種機制,用來管理必須成批的執行MySQL操作,以保證數據庫不包含不完整的操作結果。
利用事務機制可以保證一組操作不會中途停止,他們要么作為整體執行,要么完全不執行(除非明確指示),如果沒有發生錯誤,整組sql語句都會執行將數據寫入到數據庫,如果出現錯誤,則進行回退(撤銷)恢復到這組操作之前的數據狀態。
使用事務后相同的操作就會變成
1、檢查數據庫中是否存在相應的客戶,如果不存在,添加他/她
2、提交客戶信息
3、檢索客戶的ID
4、添加一行到orders 表
5、如果在添加行到orders 表時處理故障,回退
6、檢索orders 表中賦予的新訂單ID
7、對於訂購的每項物品,添加新行到orderitems表
8、如果在添加新行到orderitems時出現故障,回退所添加的orderitems 行和orders 行
9、提交訂單信息