MySql 事務與鎖


事務介紹

首先,什么是事務?事務就是一段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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM