1. 程式人生 > 其它 >MySQL 面試題:事務

MySQL 面試題:事務

設定事務隔離級別的理由?

在效能和併發影響之間做個平衡。

MySQL 的事務隔離級別有哪幾種,併發時不同的級別會造成哪些影響?

  • 如果一個事務讀到了另一個未提交事務修改過的資料,那就意味著發生了髒讀。
  • 如果一個事務只能讀到另一個已經提交的事務修改過的資料,並且其他事務每對該資料進行一次修改並提交後,該事務都能查詢得到最新值,那就意味著發生了不可重複讀。
  • 如果一個事務先根據某些條件查詢出一些記錄,之後另一個事務又向表中插入了符合這些條件的記錄,原先的事務再次按照該條件查詢時,能把另一個事務插入的記錄也讀出來,那就意味著發生了幻讀。(mysql 的 rr 一定程度解決了幻讀)

介紹一下 MVCC 。

所謂的 MVCC(Multi-Version Concurrency Control ,多版本併發控制)指的就是在使用 READ COMMITTD、REPEATABLE READ 這兩種隔離級別的事務在執行普通的 SELECT 操作時訪問記錄的版本鏈的過程,這樣子可以使不同事務的讀-寫、寫-讀操作併發執行,從而提升系統性能。READ COMMITTD、REPEATABLE READ 這兩個隔離級別的一個很大不同就是:生成 ReadView 的時機不同,READ COMMITTD 在每一次進行普通 SELECT 操作前都會生成一個 ReadView,而 REPEATABLE READ 只在第一次進行普通 SELECT 操作前生成一個 ReadView,之後的查詢操作都重複使用這個 ReadView 就好了。

如何避免長事務對業務的影響?

首先,從應用開發端來看:

  1. 確認是否使用了 set autocommit=0。這個確認工作可以在測試環境中開展,把 MySQL 的 general_log 開起來,然後隨便跑一個業務邏輯,通過 general_log 的日誌來確認。一般框架如果會設定這個值,也就會提供引數來控制行為,你的目標就是把它改成
  2. 確認是否有不必要的只讀事務。有些框架會習慣不管什麼語句先用 begin/commit 框起來。我見過有些是業務並沒有這個需要,但是也把好幾個 select 語句放到了事務中。這種只讀事務可以去掉
  3. 業務連線資料庫的時候,根據業務本身的預估,通過 SET MAX_EXECUTION_TIME 命令,來控制每個語句執行的最長時間,避免單個語句意外執行太長時間。

其次,從資料庫端來看:

  1. 監控 information_schema.Innodb_trx 表,設定長事務閾值,超過就報警 / 或者 kill;
  2. Percona 的 pt-kill 這個工具不錯,推薦使用;
  3. 在業務功能測試階段要求輸出所有的 general_log,分析日誌行為提前發現問題;
  4. 如果使用的是 MySQL 5.6 或者更新版本,把 innodb_undo_tablespaces 設定成 2(或更大的值)。如果真的出現大事務導致回滾段過大,這樣設定後清理起來更方便。