事務介紹
首先,什麼是事務?事務就是一段sql 語句的批處理,但是這個批處理是一個atom(原子),不可分割,要麼都執行,要麼復原(rollback)都不執行。
MySQL 事務主要用于處理操作量大,複雜度高的資料。比如說,在人員管理系統中,你删除一個人員,你即需要删除人員的基本資料,也要删除和該人員相關的資訊,如信箱,文章等等,這樣,這些資料庫操作語句就構成一個事務!
- 在 MySQL 中隻有使用了 Innodb 資料庫引擎的資料庫或表才支援事務。
- 事務處理可以用來維護資料庫的完整性,保證成批的 SQL 語句要麼全部執行,要麼全部不執行。
- 事務用來管理 insert,update,delete 語句
一般來說,事務是必須滿足4個條件(ACID): Atomicity(原子性)、Consistency(穩定性)、Isolation(隔離性)、Durability(可靠性)
- 1、事務的原子性:一組事務,要麼成功;要麼撤回。
- 2、穩定性 :有非法資料(外鍵限制之類),事務撤回。
- 3、隔離性:事務獨立運作。一個事務處理後的結果,影響了其他事務,那麼其他事務會撤回。事務的100%隔離,需要犧牲速度。
- 4、可靠性:軟、硬體崩潰後,InnoDB資料表驅動會利用日志檔案重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 選項 決定什麼時候吧事務儲存到日志裡。

事務并發并不進行事務隔離造成的髒讀、幻讀、不可重複讀
- 髒讀:事務A讀到未送出事務B修改的資料,如果此時事務B中途執行失敗復原,那麼此時事務A讀取到的就是髒資料。比如事務A對money進行修改,此時事務B讀取到事務A的更新結果,但是如果後面事務A復原,那麼事務B讀取到的就是髒資料了。
- 不可重複讀:同一個事務中,對同一份資料讀取的結果不一緻。事務A在事務B對資料更新前進行讀取,然後事務B更新送出,事務A再次讀取,這時候兩次讀取的資料不同。
- 幻讀:(同一個事務中,同一個查詢多次傳回的結果不一樣。事務B查詢表的記錄數,然後事務A對表插入一條記錄,接着事務B再次查詢發現記錄數不同。注意這個解釋是不正确,網絡上有很多這樣的解釋,包括我認為比較權威的專家,但是經過實驗發現并不正确。是以這是需要注意的)。可以做這樣一個實驗,事務A查詢記錄數,事務B插入一條記錄(主鍵值為6),送出,然後事務A查詢記錄數,發現記錄數沒有改變,但是此時插入一條主鍵值為6的記錄發現沖突了,感覺像出現了幻覺。
差別
1、髒讀和不可重複讀:髒讀是事務讀取了還未送出事務的更新資料。不可重複讀是同一個事務中,幾次讀取的資料不同。
2、不可重複讀和幻讀的差別:都是在同一個事務中,前者是幾次讀取資料不同,後者是幾次讀取資料整體不同。
隔離級别
作用 | |
---|---|
Serializable(串行化) | 避免髒讀、不可重複讀、幻讀 |
Repeatable(可重複讀) | 避免髒讀、不可重複讀 |
Read committed(讀已送出) | 避免髒讀 |
Read uncommitted(讀未送出) | none |
- 隔離級别改變影響鎖的周期
- mysql支援上面4種隔離級别,預設為可重複讀
鎖
MySQL有三種鎖的級别:頁級、表級、行級。
MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level locking);
BDB存儲引擎采用的是頁面鎖(page-level locking),但也支援表級鎖;
InnoDB存儲引擎既支援行級鎖(row-level locking),也支援表級鎖,但預設情況下是采用行級鎖。
MySQL這3種鎖的特性可大緻歸納如下:
1、表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的機率最高,并發度最低。
表級鎖讓多線程可以同時從資料表中讀取資料,但是如果另一個線程想要寫資料的話,就必須要先取得排他通路(預設加排他表鎖);(共享讀鎖(Table Read Lock))
更新資料時,必須要等到更新完成了,其他線程才能通路(讀)這個表。(獨占寫鎖(Table Write Lock))
2、行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的機率最低,并發度也最高。
3、頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般。
原則上資料表有一個讀鎖時,其它程序無法對此表進行更新操作,但在一定條件下,MyISAM表也支援查詢和插入操作的并發進行。
一般MyISAM引擎的表也支援查詢和插入操作的并發進行(原則上資料表有一個讀鎖時,其它程序無法對此表進行更新操作)
MyISAM引擎有一個系統變量concurrent_insert,專門用以控制其并發插入的行為,其值分别可以為0、1或2:
a、concurrent_insert為0,不允許并發插入。
b、concurrent_insert為1,如果MyISAM表中沒有空洞(即表的中間沒有被删除的行),MyISAM允許在一個程序讀表的同時,另一個程序從表尾插入記錄。這也是MySQL的預設設定。
c、concurrent_insert為2,無論MyISAM表中有沒有空洞,都允許在表尾并發插入記錄。
如果有讀寫請求同時進行的話,MYSQL将會優先執行寫操作。這樣MyISAM表在進行大量的更新操作時(特别是更新的字段中存在索引的情況下),會造成查詢操作很難獲得讀鎖,進而導緻查詢阻塞。
我們還可以調整MyISAM讀寫的優先級别:
a、通過指定啟動參數low-priority-updates,使MyISAM引擎預設給予讀請求以優先的權利。
b、通過執行指令SET LOW_PRIORITY_UPDATES=1,使該連接配接發出的更新請求優先級降低。
c、通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優先級。
MyISAM使用的是 flock 類的函數,直接就是對整個檔案進行鎖定(叫做檔案鎖定),MyISAM的資料表是按照單個檔案存儲的,可以針對單個表檔案進行鎖定;
InnoDB使用的是 fcntl 類的函數,可以對檔案中局部資料進行鎖定(叫做行鎖定),InnoDB是一整個檔案,把索引、資料、結構全部儲存在 ibdata 檔案裡,是以必須用行鎖定。
事物控制語句:
BEGIN或START TRANSACTION;顯式地開啟一個事務;
COMMIT;也可以使用COMMIT WORK,不過二者是等價的。COMMIT會送出事務,并使已對資料庫進行的所有修改稱為永久性的;
ROLLBACK;有可以使用ROLLBACK WORK,不過二者是等價的。復原會結束使用者的事務,并撤銷正在進行的所有未送出的修改;
SAVEPOINT identifier;SAVEPOINT允許在事務中建立一個儲存點,一個事務中可以有多個SAVEPOINT;
RELEASE SAVEPOINT identifier;删除一個事務的儲存點,當沒有指定的儲存點時,執行該語句會抛出一個異常;
ROLLBACK TO identifier;把事務復原到标記點;
SET TRANSACTION;用來設定事務的隔離級别。InnoDB存儲引擎提供事務的隔離級别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。
MYSQL 事務處理主要有兩種方法:
1、用 BEGIN, ROLLBACK, COMMIT來實作
BEGIN 開始一個事務
ROLLBACK 事務復原
COMMIT 事務确認
2、直接用 SET 來改變 MySQL 的自動送出模式:
SET AUTOCOMMIT=0 禁止自動送出
SET AUTOCOMMIT=1 開啟自動送出
注意點
1、如果事務中sql正确運作,後面沒有commit,結果是不會更新到資料庫的,是以需要手動添加commit。
2、如果事務中部分sql語句出現錯誤,那麼錯誤語句後面不會執行。而我們可能會認為正确操作會復原撤銷,但是實際上并沒有撤銷正确的操作,此時如果再無錯情況下進行一次commit,之前的正确操作會生效,資料庫會進行更新。
參考連結:
https://www.cnblogs.com/leonardchen/p/7048187.html
https://www.cnblogs.com/metoy/p/5545580.html
http://blog.csdn.net/andyxm/article/details/44810313
作者:Eric Li
出處:http://www.cnblogs.com/ericli-ericli/
除轉載文章外,随筆版權歸作者和部落格園所有,歡迎轉載,轉載請标明出處。
如果您覺得本篇博文對您有所收獲,覺得作者還算用心,請點選右下角的 [推薦],謝謝!