這一篇讓你徹底認識mysql事務

微信搜索BGM7756,免費獲取文末的面試資料!


引言

今天回頭繼續講講數據庫系列的文章。這篇文章屬於mysql數據庫系列,咱們來談談事務方面的常見面試題。那麼,具體題目有下面這些:一、講講爲何用事務?事物的四大特性?事務的隔離級別知道吧,大家生產用哪一種?二、Innodb中ACID具體是如何實現的?三、redo log和binlog的一致性如何保證?四、大事務有哪些壞處?生產上遇到過大事務麼?你怎麼排查和解決的?五、你有遇到過數據庫宕機重啓,事務丟失的狀況麼?六、可重複讀是怎麼實現的?mysql

再三強調,每一個問題都仔細看!都是高頻題!切勿遺漏!程序員

正文

一、講講爲何用事務?事物的四大特性?事務的隔離級別知道吧,大家生產用哪一種?回答:爲何用事務?面試

這個問題從事務的四大特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability),這四個角度去答。例如原子性的角度,張三給李四轉帳,只有當張三帳戶的錢轉走了,而且李四帳戶的錢收到了以後轉帳事務才能提交。若是原子性沒法保證,就會出現張三的錢轉走了,李四卻沒收到錢的狀況!spring

Come on!這種easy回答,我就不一個個舉例了,過!sql

至於生產用哪一種隔離級別?答Read Commited或者Repeatable都行,有道理便可。例如,我用了Read Commited,由於這個隔離級別夠用了,用不上間隙鎖!詳情能夠參照《互聯網項目中mysql應該選什麼事務隔離級別》這篇文章!數據庫

另外,額外記住Repeatable是默認的隔離級別便可!至於另外兩個隔離級別,Read uncommitted,一個事務能讀到另外一個事務未提交的數據,隔離性都沒法知足,不用這個隔離級別。另一個隔離級別Seriallzable,在這個隔離級別下,MVCC機制都沒法知足,數據庫併發性很是差,不用這個隔離級別。緩存

ps:這個問題其實考察的是你對各個隔離級別的理解,因此務必牢記各個隔離級別的區別!bash

二、Innodb中ACID具體是如何實現的?回答:老題了,詳細版,能夠看這篇文章《程序員,知道Mysql中事務ACID的原理嗎?》這裏給出簡單回答,微信

  • (1)利用undo log保證原子性
  • (2)利用redo log保證持久性
  • (3)利用鎖和MVCC機制保證隔離性
  • (4)經過原子性、持久性、隔離性來保證一致性

三、redo log和binlog的一致性如何保證?回答:此題,先回憶一下redo log和binlog的區別!redo log 記錄的是數據的物理變化,因此叫物理日誌,記錄的是是物理修改的內容(xxxx頁修改了xxx)。當咱們修改數據的時候,寫完內存了,但數據還沒真正寫到磁盤的時候。此時咱們的數據庫掛了,咱們能夠根據redo log來對數據進行恢復!併發

binlog 記錄的是數據的邏輯變化,因此又叫邏輯日誌,statement模式下記載的是update/delete/insert這樣的SQL語句,主要用來主從複製和恢復數據用。

這兩者功能很像,都是用做」恢復「的!所以這二兩個日誌必須保證邏輯上一致,不然就會出現數據錯亂。例如,咱們先寫redo log再寫binlog。在redo log寫完後,宕機了,此時binlog來不及寫。那麼重啓後,數據可以根據redo log進行恢復,可是binlog沒記錄這個語句。那麼,咱們在利用這個binlog恢復數據的時候,就會出現丟失數據的情形!

mysql怎麼解決的?這裏考察的是mysql的內部XA事務!俗稱日誌的兩階段提交協議!也就是說,將事務提交分爲了兩個階段,prepare階段和commit階段!

prepare:寫入redo log,並將回滾段置爲prepared狀態,此時binlog不作操做。

commit:innodb釋放鎖,釋放回滾段,設置提交狀態,寫入binlog,而後存儲引擎層提交。

mysql數據庫怎麼進行崩潰恢復的?1> 崩潰恢復時,掃描最後一個Binlog文件,提取其中的xid;2> InnoDB維持了狀態爲Prepare的事務鏈表,將這些事務的xid和binlog中記錄的xid作比較,若是在binlog中存在,則提交,不然回滾事務。

最後,這道題藍綠大廠,開水團,宇宙條都問過!

四、大事務有哪些壞處?生產上遇到過大事務麼?你怎麼排查和解決的?回答:大事務,有的文章又稱之爲長事務,顧名思義,執行時間很長的事務!

至於壞處,例如事務執行時間太長,會形成大量的阻塞和鎖超時,容易形成主從延遲.另外,大事務若是執行失敗,回滾也會很耗時…(省略一千字)

怎麼排查?so easy!監控information_schema.Innodb_trx表,設置長事務閾值,超過就報警 / 或者 kill;

下面語句是查詢持續時間超過60s的事務

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60;複製代碼

通常在生產中,會將監控大事務的語句,配成定時腳本,進行監控。

至於怎麼解決?結合業務場景,優化SQL,將一個大事務拆成多個小事務執行,或者縮短事務執行時間便可。

五、你有遇到過數據庫宕機重啓,事務丟失的狀況麼?回答:此題考查的是,sync_binlog配置(控制binlog刷盤時機)和innodb_flush_log_at_trx_commit配置(配置redolog刷盤時機)因爲這兩個配置的搭配組合不少種,一一舉例,太麻煩了,我隨意舉幾個例子(1)innodb_flush_log_at_trx_commit=1 和 sync_binlog=0這是mysql的默認配置,表示每次事務提交時都將 redo log 直接持久化到磁盤.可是MySQL不控制binlog的刷新,由操做系統本身控制它的緩存的刷新。

若是你答的是這套配置,那風險就是一旦系統宕機,在binlog_cache中的全部binlog信息都會被丟失。因而乎,你能夠再結合上本身的公司背景來答。例如,咱們公司規模不大,你們沒有技術沉澱,所以沒有修改過mysql的默認配置。可是,我私底下有過了解(突出本身勤奮好學),在該配置狀況下,這兩個參數的值爲XXX,理論上操做系統宕機,有XXX的風險。可是,操做系統宕機的概率很低,所以咱們也沒怎麼碰見過事務丟失的狀況。

(2)innodb_flush_log_at_trx_commit=1 和 sync_binlog=1不少文章提到的雙1配置。表示每次事務提交時都將redolog直接持久化到磁盤,binlog也會持久化到磁盤。

無疑,這個配置一致性最好,不會丟數據,可是性能是最差的。若是你答的是這套配置,你能夠這麼答,咱們系統涉及到一些金錢相關的業務邏輯,寧願慢,也不能一致性出錯,所以咱們的配置爲XXX。至於性能問題,咱們能夠經過一些緩存,或者異步化設計進行改良。

(3)innodb_flush_log_at_trx_commit=2 和 sync_binlog=0性能最好的一套配置,表示每次事務提交時,只是把redolog寫到OS cache,隔一秒,MySQL主動將OS cache中的數據批量fsync。而MySQL不控制binlog的刷新,由操做系統本身控制它的緩存的刷新。風險就是,操做系統一旦宕機,會丟數據。

這套配置下併發性最好。若是答這個配置,你能夠說咱們業務對併發的要求相對高一些,所以修改過XX參數。可是有操做系統宕機,丟數據的風險。可是,在實際環境中,操做系統崩潰的機率相比MySQL應用程序崩潰的機率,小不少…(自由發揮)

不一一舉例,言之有理便可!記住,全靠一張嘴,說得通就是你的!說不通,回去總結一下,換一家繼續說!無他,惟熟爾!

六、可重複讀是怎麼實現的?回答:這道題坦白說,我不懂面試官想聽哪一個角度的回答。我只能說一下個人理解,主要有如下兩個緣由(1)利用間隙鎖,防止幻讀的出現,保證了可重複讀幻讀的問題存在是由於新增或者更新操做,這時若是進行範圍查詢的時候(加鎖查詢),會出現不一致的問題,這時使用不一樣的行鎖已經沒有辦法知足要求,須要對必定範圍內的數據進行加鎖。

(2)MVCC的快照生成時機不一樣在可重複讀這個隔離級別下,遇到當事務中的第一個SELECT請求才建立read view,所以你是沒法讀到其餘事務提交的更改。而在讀已提交這個隔離級別下,每一個SELECT都會獲取最新的read view,所以你能讀到其餘事務提交的數據。

由於,這個View生成時機不一樣,因此實現了可重複讀。此題答案,有不一樣看法能夠討論一下。反正我是沒懂,這一題到底是想問什麼!

總結

OK,但願本文你們有所收穫!

本文其實對事務方面的問題沒講全,由於在面試的時候一般會結合spring的事務和分佈式事務來問,例如什麼狀況下spring事務會失效啊,巴拉巴拉。

微信搜索BGM7756,免費獲取如下面試資料!


關於面試我還經過一些渠道整理了須要大廠真實面試主要有:螞蟻金服、拼多多、阿里雲、百度、惟品會、攜程、等初級,中級,高級Java面試題集合,附帶超詳細答案,但願能幫助到你們。


相關文章
相關標籤/搜索