mysql事务总结_MySQL数据库和相关事务总结
以下的文章主要向大家描述的是MySQL數(shù)據(jù)庫和相關(guān)事務(wù),在實際操作中有很多人都認為MySQL數(shù)據(jù)庫對事務(wù)處理是不支持的,其實,只要MySQL數(shù)據(jù)庫版本支持BDB或是InnoDB表類型,那么你的MySQL就具有事務(wù)處理的能力。
這里面,又以InnoDB表類型用的最多,雖然后來發(fā)生了諸如Oracle收購InnoDB等令MySQL不爽的事情,但那些商業(yè)上的斗爭與技術(shù)無關(guān),下面以InnoDB表類型為例簡單說一下MySQL中的事務(wù)。
先來明確一下事務(wù)涉及的相關(guān)知識:
事務(wù)都應(yīng)該具備ACID特征。所謂ACID是Atomic(原子性),Consistent(一致性),Isolated(隔離性),Durable(持續(xù)性)四個詞的首字母所寫,下面以“銀行轉(zhuǎn)帳”為例來分別說明一下它們的含義:
原子性:組成事務(wù)處理的語句形成了一個邏輯單元,不能只執(zhí)行其中的一部分。換句話說,事務(wù)是不可分割的最小單元。比如:銀行轉(zhuǎn)帳過程中,必須同時從一個帳戶減去轉(zhuǎn)帳金額,并加到另一個帳戶中,只改變一個帳戶是不合理的。
一致性:在事務(wù)處理執(zhí)行前后,MySQL數(shù)據(jù)庫是一致的。也就是說,事務(wù)應(yīng)該正確的轉(zhuǎn)換系統(tǒng)狀態(tài)。比如:銀行轉(zhuǎn)帳過程中,要么轉(zhuǎn)帳金額從一個帳戶轉(zhuǎn)入另一個帳戶,要么兩個帳戶都不變,沒有其他的情況。
隔離性:一個事務(wù)處理對另一個事務(wù)處理沒有影響。就是說任何事務(wù)都不可能看到一個處在不完整狀態(tài)下的事務(wù)。比如說,銀行轉(zhuǎn)帳過程中,在轉(zhuǎn)帳事務(wù)沒有提交之前,另一個轉(zhuǎn)帳事務(wù)只能處于等待狀態(tài)。
持續(xù)性:事務(wù)處理的效果能夠被***保存下來。反過來說,事務(wù)應(yīng)當能夠承受所有的失敗,包括服務(wù)器、進程、通信以及媒體失敗等等。比如:銀行轉(zhuǎn)帳過程中,轉(zhuǎn)帳后帳戶的狀態(tài)要能被保存下來。
再來看看哪些問題會用到事務(wù)處理:
這里不說“銀行轉(zhuǎn)帳”的例子了,說一個大家實際更容易遇到的“網(wǎng)上購書”的例子。先假設(shè)一下問題的背景:網(wǎng)上購書,某書(MySQL數(shù)據(jù)庫編號為123)只剩***一本,而這個時候,兩個用戶對這本書幾乎同時發(fā)出了購買請求,讓我們看看整個過程:
在具體分析之前,先來看看數(shù)據(jù)表的定義:
create?table?book
(
book_id?unsigned?int(10)?not?null?auto_increment,
book_name?varchar(100)?not?null,
book_price?float(5,?2)?not?null,?#我假設(shè)每本書的價格不會超過999.99元
book_number?int(10)?not?null,
primary?key?(book_id)
)
type=innodb;?#engine=innodb也行
對于用戶甲來說,他的動作稍微比乙快一點點,其購買過程所觸發(fā)的動作大致是這樣的:
1. SELECT book_number FROM book WHERE book_id = 123;
book_number大于零,確認購買行為并更新book_number
2. UPDATE book SET book_number = book_number - 1 WHERE book_id = 123;
購書成功
而對于用戶乙來說,他的動作稍微比甲慢一點點,其購買過程所觸發(fā)的動作和甲相同:
1. SELECT book_number FROM book WHERE book_id = 123;
這個時候,甲剛剛進行完***步的操作,還沒來得及做第二步操作,所以book_number一定大于零
2. UPDATE book SET book_number = book_number - 1 WHERE book_id = 123;
購書成功
表面上看甲乙的操作都成功了,他們都買到了書,但是庫存只有一本,他們怎么可能都成功呢?再看看數(shù)據(jù)表里book_number的內(nèi)容,已經(jīng)變成“-1”了,這當然是不能允許的(實際上,聲明這樣的列類型應(yīng)該加上unsigned的屬性,以保證其不能為負,這里是為了說明問題所以沒有這樣設(shè)置)
好了,問題陳述清楚了,再來看看怎么利用事務(wù)來解決這個問題,打開MySQL手冊,可以看到想用事務(wù)來保護你的SQL正確執(zhí)行其實很簡單,基本就是三個語句:開始,提交,回滾。
開始:START TRANSACTION或BEGIN語句可以開始一項新的事務(wù)
提交:COMMIT可以提交當前事務(wù),是變更成為***變更
回滾:ROLLBACK可以回滾當前事務(wù),取消其變更
此外,SET AUTOCOMMIT = {0 | 1}可以禁用或啟用默認的autocommit模式,用于當前連接。
那是不是只要用事務(wù)語句包一下我們的SQL語句就能保證正確了呢?比如下面代碼:
BEGIN;
SELECT?book_number?FROM?book?WHEREbook_id=123;
//?...
UPDATE?book?SETbook_numberbook_number=?book_number?-?1?WHEREbook_id=123;
COMMIT;
答案是否定了,這樣依然不能避免問題的發(fā)生,如果想避免這樣的情況,實際應(yīng)該如下:
BEGIN;
SELECT?book_number?FROM?book?WHEREbook_id=123FOR?UPDATE;
//?...
UPDATE?book?SETbook_numberbook_number=?book_number?-?1?WHEREbook_id=123;
COMMIT;
由于加入了FOR UPDATE,所以會在此條記錄上加上一個行鎖,如果此事務(wù)沒有完全結(jié)束,那么其他的事務(wù)在使用SELECT ... FOR UPDATE請求的時候就會處于等待狀態(tài),直到上一個事務(wù)結(jié)束,它才能繼續(xù),從而避免了問題的發(fā)生,需要注意的是,如果你其他的事務(wù)使用的是不帶FOR UPDATE的SELECT語句,將得不到這種保護。
以上的相關(guān)內(nèi)容就是對MySQL數(shù)據(jù)庫與事務(wù)的介紹,望你能有所收獲。
【編輯推薦】
【責任編輯:孫巧華 TEL:(010)68476606】
點贊 0
總結(jié)
以上是生活随笔為你收集整理的mysql事务总结_MySQL数据库和相关事务总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: react --- render持续调
- 下一篇: swift4视频课程 swift5入门教