MySQL事務(wù)底層實現(xiàn)原理

雨中獨奏IP屬地: 四川
0.335字?jǐn)?shù) 1,945

事務(wù)特性

事務(wù)特性分為:
原子性 每一個事務(wù)都是不可分割的整體,要么全部成功要么全部失敗;
一致性 事務(wù)執(zhí)行后的結(jié)果是和預(yù)設(shè)的規(guī)則完全符合的,不會因為出現(xiàn)系統(tǒng)意外等原因和預(yù)測的結(jié)果不一致;
隔離性 事務(wù)與事務(wù)之間是相互獨立的,互不影響;也是在事務(wù)并發(fā)時實現(xiàn)一致性的一個前提,可以設(shè)置4種隔離級別。級別越高一致性越強,但并發(fā)性越低;

1.讀未提交 會讀到其他事務(wù)未提交的數(shù)據(jù),產(chǎn)生臟讀
2.讀已提交 解決臟讀,但在同一事務(wù)中多次讀取單行數(shù)據(jù)會得到不同結(jié)果,即不可重復(fù)讀的問題
3.可重復(fù)讀 解決不可重復(fù)讀,但會在多次范圍查詢時,得到數(shù)量不同的結(jié)果,即幻讀。在innodb引擎中,不會存在此問題,實現(xiàn)原理是臨鍵鎖。
4.可串行化 解決幻讀

持久性 事務(wù)一旦提交就會永久保存,不會因為系統(tǒng)意外原因而丟失

innodb事務(wù)的這些特性如何實現(xiàn)?鎖、MVCC

innodb一共有5種鎖:共享鎖(行)、排它鎖(行)、意向共享鎖(表)、意向排它鎖(表)、自增鎖。行鎖實現(xiàn)有三種算法,又稱為:臨鍵鎖next-key、間隙所gap和記錄鎖record。默認(rèn)隔離級別不可重復(fù)讀使用臨鍵鎖作為行鎖的實現(xiàn)算法。
InnoDB的行鎖是通過給索引上的索引項加鎖來實現(xiàn)的,只有通過索引條件進行數(shù)據(jù)檢索,InnoDB才使用行級鎖,否則InnoDB 將使用表鎖(鎖住全部索引)。

鎖的類型

1.共享鎖:也稱為讀鎖,可以讓多個事務(wù)同時對數(shù)據(jù)進行操作時可以訪問到數(shù)據(jù),但不能修改。使用方式:

select語句+LOCK IN SHARE MOD

2.排它鎖:又稱為寫鎖。一個事務(wù)持有了一行數(shù)據(jù)的排它鎖時,其他事務(wù)不能再訪問和修改這行數(shù)據(jù)。innodb默認(rèn)update delete insert上會加排它鎖,select使用方式:

select語句+for update

3.意向共享鎖:在事務(wù)對某一行加共享鎖時,要先給該表加上意向共享鎖。
4.意向排它鎖:在事務(wù)對某一行數(shù)據(jù)加排它鎖時,必須要先給該表加上意向排它鎖。
作用是,當(dāng)某一個事務(wù)需要去鎖表時,不用判斷每一行上是否有不兼容的鎖,只需要判斷有沒有意向鎖。如寫操作鎖表,判斷某行數(shù)據(jù)是否存在共享鎖,如果拿不到意向鎖就可直接阻塞操作。
5.自增鎖:針對自增列自增長的一個特殊的表級別鎖。

鎖的算法

1.臨鍵鎖next-key:當(dāng)sql語句按照范圍查詢,并且有數(shù)據(jù)命中的時候會給索引加上臨鍵鎖,鎖住命中索引項的前一個索引到命中索引項的后一個索引之間的一個左開右閉區(qū)間。因為鎖住區(qū)間,所以避免了幻讀。
2.間隙鎖gap:當(dāng)sql語句查找未命中時,會鎖住查詢條件值附近的間隙。
3.記錄鎖record:使用唯一索引查詢并精準(zhǔn)匹配到數(shù)據(jù),則只會鎖住該索引項。
這三種算法鎖的原理基于b+tree索引。

死鎖

事務(wù)并發(fā)時,每個事務(wù)都持有鎖(或者是已經(jīng)在等待鎖),每個事務(wù)都需要再繼續(xù)持有鎖,然后事務(wù)之間產(chǎn)生加鎖的循環(huán)等待,形成死鎖。避免死鎖:
1)類似的業(yè)務(wù)邏輯以固定的順序訪問表和行。
2)大事務(wù)拆小。大事務(wù)更傾向于死鎖,如果業(yè)務(wù)允許,將大事務(wù)拆小。
3)在同一個事務(wù)中,盡可能做到一次鎖定所需要的所有資源,減少死鎖概 率。
4)降低隔離級別,如果業(yè)務(wù)允許,將隔離級別調(diào)低也是較好的選擇 。
5)為表添加合理的索引。可以看到如果不走索引將會為表的每一行記錄添 加上鎖(或者說是表鎖)

MVCC多版本并發(fā)控制

并發(fā)訪問(讀或?qū)?數(shù)據(jù)庫時,對正在事務(wù)內(nèi)處理的數(shù)據(jù)做 多版本的管理。以達(dá)到用來避免寫操作的堵塞,從而引發(fā)讀操 作的并發(fā)問題。
新增:會給行數(shù)據(jù)添加兩個隱藏列,數(shù)據(jù)版本號和刪除版本號。數(shù)據(jù)版本號值為插入時的事務(wù)id,刪除版本號默認(rèn)為null。
刪除:會給行數(shù)據(jù)的刪除版本號設(shè)一個當(dāng)前事務(wù)id值。
修改:會先拷貝一份行數(shù)據(jù),再把原先行數(shù)據(jù)的刪除版本號設(shè)值,再修改拷貝的數(shù)據(jù),并改變數(shù)據(jù)版本號值。
查詢:必須保證當(dāng)前事務(wù)ID大于等于該行數(shù)據(jù)的數(shù)據(jù)版本號,并且刪除版本號必須為null或者大于當(dāng)前事務(wù)ID值。

undo log

undo log作用是保證了事務(wù)的原子性和普通select的快照讀。當(dāng)事務(wù)開啟的時候會拷貝當(dāng)前數(shù)據(jù)到undo log中,此時有其他事務(wù)中的select讀取數(shù)據(jù)直接從undo log中獲取,若事務(wù)回滾可根據(jù)undo log恢復(fù)原始數(shù)據(jù)。

redo log

redo log保證了事務(wù)的持久性。事務(wù)開啟后,只要開始改變數(shù)據(jù)信息就會持續(xù)寫入redo buffer中,具體落盤可以指定不同的策略。在數(shù)據(jù)庫發(fā)生意外故障時,尚有修改的數(shù)據(jù)未寫入磁盤,在重啟mysql服務(wù)的時候,根據(jù)redo log恢復(fù)事務(wù)修改后的新數(shù)據(jù)。
Redo buffer 持久化到Redo log的策略有三種:
取值 0 每秒一次進行提交持久化[可能丟失一秒內(nèi) 的事務(wù)數(shù)據(jù)]
取值 1 默認(rèn)值,每次事務(wù)提交執(zhí)行Redo buffer --> Redo log OS cache -->flush cache to disk [最安全,性能最差的方式]
取值 2 每次事務(wù)提交到系統(tǒng)緩存OS cache,再每一秒從系統(tǒng)緩存中執(zhí)行持久化 操作

mysql配置優(yōu)化

最大連接數(shù)配置 max_connections

connection內(nèi)存參數(shù)配置:

sort_buffer_size connection排序緩沖區(qū)大小 建議256K(默認(rèn)值)-> 2M之內(nèi) 當(dāng)查詢語句中有需要文件排序功能時,馬上為connection分配配置的內(nèi)存大小。
join_buffer_size connection關(guān)聯(lián)查詢緩沖區(qū)大小 建議256K(默認(rèn)值)-> 1M之內(nèi) 當(dāng)查詢語句中有關(guān)聯(lián)查詢時,馬上分配配置大小的內(nèi)存用這個關(guān)聯(lián)查 詢,所以有可能在一個查詢語句中會分配很多個關(guān)聯(lián)查詢緩沖區(qū)。
上述配置4000連接占用內(nèi)存: 4000*(0.256M+0.256M) = 2G

Innodb_buffer_pool_size緩沖池大小配置

innodb buffer/cache的大小(默認(rèn)128M)
Innodb_buffer_pool緩沖池包含:數(shù)據(jù)緩存 索引緩存 緩沖數(shù)據(jù) 內(nèi)部結(jié)構(gòu)
大的緩沖池可以減小多次磁盤I/O訪問相同的表數(shù)據(jù)以提高性能
參考計算公式: Innodb_buffer_pool_size = (總物理內(nèi)存 - 系統(tǒng)運行所用 - connection 所用)* 90%

其他參數(shù)配置

wait_timeout 服務(wù)器關(guān)閉非交互連接之前等待活動的秒數(shù)
innodb_open_files 限制Innodb能打開的表的個數(shù)
innodb_write_io_threads innodb_read_io_threads innodb:使用后臺線程處理innodb緩沖區(qū)數(shù)據(jù)頁上的讀寫 I/O(輸入輸出)請求的數(shù)量
innodb_lock_wait_timeout InnoDB事務(wù)在被回滾之前可以等待一個鎖定的超時秒數(shù)

最后編輯于
©著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
3人點贊
總資產(chǎn)1共写了2.5W字获得12个赞共10个粉丝
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,003評論 2 374