事務就是一組原子性的sql查詢,或者說是一個獨立的工做單元。簡而言之,事務內的語句要麼所有執行成功,要麼所有執行失敗。mysql
在Mysql中,事務支持是在引擎層實現的,但並非全部的Mysql引擎都支持事務,好比MyISAM引擎就不支持事務,這也是MyISAM被InnoDB取代的重要緣由之一。sql
提到事務,咱們確定會想到ACID:數據庫
當數據庫中有多個事務同時執行時,就可能會出現髒讀、不可重複讀、幻讀等問題,由於就有了事務隔離級別的概念。性能
SQL標準正定義了四種隔離級別:線程
事務中的修改,即便尚未提交,對其餘事務都是可見的。事務能夠讀取未提交的數據,也被稱爲髒讀(Dirty Read)。日誌
一個事務提交後,所作的變動才能被其餘事務看到。這個級別也叫不可重複讀,由於事務中執行2次相同的查詢,可能獲得的結果是不同的。code
一個事務執行的過程當中,老是和這個事務在啓動時看到的數據是一致的。固然在這個級別下,未提交的數據變動對其餘事務也是不可見的。orm
對同一行記錄,寫和讀都會加鎖,當出現讀寫鎖衝突時,後訪問的事務必須等前一個事務執行完成才能繼續執行,就會致使大量的超時和鎖爭用的問題。事務
在實現上,數據庫裏面會建立一個視圖,訪問的時候以視圖的邏輯爲準。ci
在可重複讀這個隔離級別下,這個視圖是事務開啓的時候建立的,整個事務期間都用這個視圖。
在讀提交的隔離級別下,這個視圖是在sql語句開始執行的時候建立的。
在讀未提交的隔離級別下,直接返回記錄上的最新值,沒有視圖概念。
在串行化的隔離級別下,直接用加鎖的方式避免並行訪問。
配置的方式是將啓動參數transaction-isolation
設置成想要的隔離級別。
查看當前設置:
mysql> show variables like 'transaction_isolation'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ | transaction_isolation | REPEATABLE-READ | +-----------------------+-----------------+ 1 row in set (0.00 sec)
總之,存在即合理,不一樣的隔離級別適用於不一樣的場景,具體咱們應該根據業務場景來決定。
在Mysql中,實際上每條記錄的更新同時也會記錄一條回滾操做,記錄上的最新值經過回滾操做,均可以獲得前一個狀態的值。
系統會自動判斷,當沒有事務再須要回滾日誌時,會刪除回滾日誌。
爲何不建議使用長事務:
長事務意味着系統裏面會存在很老的事務視圖,因爲這些事務隨時能夠訪問數據庫裏面的任何數據,因此這個事務提交以前,數據庫裏可能用到的回滾記錄必須保留着,這就會佔用大量的存儲空間。同時長事務還佔用鎖資源,也可能拖垮整個庫。
我的建議仍是經過第一種方式顯式啓動事務,避免長事務的發生。
在 set autocommit = 1 的狀況下,用 begin 顯式啓動的事務,若是執行 commit 則提交事務。若是執行 commit work and chain,則是提交事務並自動啓動下一個事務,這樣也省去了再次執行 begin 語句的開銷。
查詢長事務:
下面語句是查詢持續時間超過60s的事務
mysql> select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60; Empty set (0.00 sec)
總結下來,咱們在開發過程當中,儘可能少用長事務,若是沒法避免,保證邏輯日誌空間足夠大,而且支持動態日誌空間增加。監控Innodb_trx表,發現長事務報警。
歡迎交流。
《高性能Mysql》
極客時間-Mysql實戰45講