事務的概念

2021-05-24 14:36:27 字數 2715 閱讀 5066

mysql5.x都已經發布好久了,但是還有很多人認為mysql是不支援事務處理的,這不得不怪他們是孤陋寡聞的,其實,只要你的mysql版本支援bdb或innodb表型別,那麼你的mysql就具有事務處理的能力。這裡面,又以innodb表型別用的最多,雖然後來發生了諸如oracle收購innodb等令mysql不爽的事情,但那些商業上的鬥爭與技術無關,下面以innodb表型別為例簡單說一下mysql中的事務。

事務都應該具備acid特徵。所謂acid是atomic(原子性),consistent(一致性),isolated(隔離性),durable(持續性)四個詞的首字母所寫,下面以「銀行轉帳」為例來分別說明一下它們的含義:

原子性:組成事務處理的語句形成了乙個邏輯單元,不能只執行其中的一部分。換句話說,事務是不可分割的最小單元。比如:銀行轉帳過程中,必須同時從乙個帳戶減去轉帳金額,並加到另乙個帳戶中,只改變乙個帳戶是不合理的。

一致性:在事務處理執行前後,資料庫是一致的。也就是說,事務應該正確的轉換系統狀態。比如:銀行轉帳過程中,要麼轉帳金額從乙個帳戶轉入另乙個帳戶,要麼兩個帳戶都不變,沒有其他的情況。

隔離性:乙個事務處理對另乙個事務處理沒有影響。就是說任何事務都不可能看到乙個處在不完整狀態下的事務。比如說,銀行轉帳過程中,在轉帳事務沒有提交之前,另乙個轉帳事務只能處於等待狀態。

持續性:事務處理的效果能夠被永久儲存下來。反過來說,事務應當能夠承受所有的失敗,包括伺服器、程序、通訊以及**失敗等等。比如:銀行轉帳過程中,轉帳後帳戶的狀態要能被儲存下來。

再來看看哪些問題會用到事務處理:

這裡不說「銀行轉帳」的例子了,說乙個大家實際更容易遇到的「網上購書」的例子。先假設一下問題的背景:網上購書,某書(資料庫編號為123)只剩最後一本,而這個時候,兩個使用者對這本書幾乎同時發出了購買請求,讓我們看看整個過程:

在具體分析之前,先來看看資料表的定義:

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, #我假設每本書的**不會超過999.99元

book_number int(10) not null,

primary key (book_id)

)type = innodb; #engine = innodb也行

對於使用者甲來說,他的動作稍微比乙快一點點,其購買過程所觸發的動作大致是這樣的:

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;

購書成功

而對於使用者乙來說,他的動作稍微比甲慢一點點,其購買過程所觸發的動作和甲相同:

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;

購書成功

表面上看甲乙的操作都成功了,他們都買到了書,但是庫存只有一本,他們怎麼可能都成功呢?再看看資料表裡book_number的內容,已經變成「-1」了,這當然是不能允許的(實際上,宣告這樣的列型別應該加上unsigned的屬性,以保證其不能為負,這裡是為了說明問題所以沒有這樣設定)

好了,問題陳述清楚了,再來看看怎麼利用事務來解決這個問題,開啟mysql手冊,可以看到想用事務來保護你的sql正確執行其實很簡單,基本就是三個語句:開始,提交,回滾。

開始:start transaction或begin語句可以開始一項新的事務

提交:commit可以提交當前事務,是變更成為永久變更

回滾:rollback可以回滾當前事務,取消其變更

此外,set autocommit = 可以禁用或啟用預設的autocommit模式,用於當前連線。

那是不是只要用事務語句包一下我們的sql語句就能保證正確了呢?比如下面**:

begin;

select book_number from book where  book_id = 123;

update book set book_number = book_number - 1 where  book_id = 123;

commit;

答案是否定了,這樣依然不能避免問題的發生,如果想避免這樣的情況,實際應該如下:

begin;

select book_number from book where  book_id = 123 for update;

update book set book_number = book_number - 1 where  book_id = 123;

commit;

由於加入了for update,所以會在此條記錄上加上乙個行鎖,如果此事務沒有完全結束,那麼其他的事務在使用select ... for update請求的時候就會處於等待狀態,直到上乙個事務結束,它才能繼續,從而避免了問題的發生,需要注意的是,如果你其他的事務使用的是不帶for update的select語句,將得不到這種保護。

事務的概念

1.什麼是事務 所謂的事務,它是乙個操作序列,這組操作序列要麼都執行,要麼都不執行,它是不可分割的工作單位 所謂的事務,它是一組的sql語句的序列,這組操作序列要麼都執行,要麼都不執行,它是不可分割的工作單位 2.事務的特性 原子性a 乙個事務是乙個不可分割的工作單位,事務中包括的操作要麼都做要麼都...

事務的概念

1 事務 transaction 是併發控制的單位,是使用者定義的乙個操作序列。這些操作要麼都做,要麼都不做,是乙個不可分割的工作單位。通過事務,sql server能將邏輯相關的一組操作繫結在一起,以便伺服器保持資料的完整性。2 事務通常是以begin transaction開始,以commit或...

事務的概念

事務 acid a原子性 要麼一起成功,要麼一起失敗 c一致性 讀不等待寫,寫不等待讀 i隔離性 未提交資料之前不可見 d永續性 資料提交後不可丟失 update balance balance 500 where username a 異常update balance balance 500 wh...