標籤:
mysql事物主要用於處理操作量大,複雜度高的資料。比如說,在人員管理系統中,你刪除一個人員,你既要刪除人員的基本資料,也要刪除和該人員相關的資訊,如信箱,文章等。這樣,這些資料庫動作陳述式就構成一個事物。注意一下幾點:
- 在MySQL中只有使用了Innodb資料庫引擎的資料庫或表才支援事務。
- 事物處理可以用來維護資料庫的完整性,保證成批的sql語句要麼全部執行,要麼全部不執行。
- 事物用來管理insert,update,delete語句。
先簡單介紹一下事物吧。事物是DBMS的執行單位。它由有限的資料庫操作序列組成的,但不是任意的資料庫操作序列都能成為事物。一般來說,事物必須滿足4個條件(ACID):
原子性:組成事物處理的語句形成了一個邏輯單元,不能只執行其中一部分。換句話說,事物是不可分割的最小單元。比如銀行轉賬過程中,必須同時從一個賬戶減去轉賬金額,並加到另一個賬戶中,只改變一個賬戶是不合理的。
一致性:在事物處理執行前後,mysql資料庫是一致的。也就是說,事物應該正確的轉換系統狀態。比如銀行轉賬過程中,要麼轉賬金額從一個賬戶到另一個賬戶,要麼兩個賬戶都不變,沒有其他情況。
隔離性:一個事物處理對另外一個事物處理沒有影響。比如說銀行轉賬過程中,在轉賬事物沒有提交之前,另一個轉賬事物只能處於等待狀態 。
可靠性:事物處理的效果能夠被永久儲存下來。反過來說,事物能夠承受所有的失敗。包括伺服器,進程,通訊以及媒體失敗等等。比如銀行轉賬過程中,轉賬後賬戶的狀態要能被儲存下來。
mysql的事物處理主要有兩種方法:
1. begin,rollback,commit來實現
begin 開始一個事物
rollback 事物復原
commit 事物確認,事物提交
2,直接用set來改變mysql的自動認可模式
mysql預設z是自動認可的,也就是你提交一個query,它就直接執行。
set autocommit = 0 禁止自動認可模式
set autocommit = 1 開啟自動認可模式
mysql中只用INNODB和BDB類型的資料表才能支援事物處理(切記)!
來看一個例子:
先假設一下問題的背景:網上購書,某書《mysql資料庫》編號為123,只剩最後一本,而這個時候兩個使用者幾乎同時對這本書發出了購書請求,讓我們來看看整個過程:
在具體分析之前,先來看看資料表的定義:
對於使用者甲來說,他的動作稍微比乙快一點點,其購買過程中所觸發的動作大致是這樣的:
1.select book_number from book where book_id = 123;
book_number 大於0,購買行為並更新book_number
2.update book set book_number = book_number—1 where book_id = 123;
購書成功
表面上看甲乙的操作都成功了,他們都買到了書,但是庫存只有一本,他們怎麼可能都成功呢?再看看資料表裡book_number的內容,已經變成“-1”了,這當然是不能允許的(實際上,聲明這樣的列類型應該加上unsigned的屬性,以保證其不能為負,這裡是為了說明問題所以沒有這樣設定)
好了,問題陳述清楚了,再來看看怎麼利用事務來解決這個問題,開啟MySQL手冊,可以看到想用事務來保護你的SQL正確執行其實很簡單,基本就是三個語句:開始,提交,復原。
開始:START TRANSACTION或BEGIN語句可以開始一項新的事務
提交:COMMIT可以提交當前事務,是變更成為永久變更
復原:ROLLBACK可以復原當前事務,取消其變更
此外,SET AUTOCOMMIT = {0 | 1}可以禁用或啟用預設的autocommit模式,用於當前串連。
那是不是只要用事務語句包一下我們的SQL語句就能保證正確了呢?比如下面代碼:
答案是否定了,這樣依然不能避免問題的發生,如果想避免這樣的情況,實際應該如下:
由於加入了FOR UPDATE,所以會在此條記錄上加上一個行鎖,如果此事務沒有完全結束,那麼其他的事務在使用SELECT ... FOR UPDATE請求的時候就會處於等待狀態,直到上一個事務結束,它才能繼續,從而避免了問題的發生,需要注意的是,如果你其他的事務使用的是不帶FOR UPDATE的SELECT語句,將得不到這種保護。
mysql事物處理