'程序員的MySQL攻略,總結的非常全面系統'

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

程序員的MySQL攻略,總結的非常全面系統

查詢流程

再看一下一個SQL的執行過程,SQL Cache->解析器->優化器->執行引擎->存儲引擎;是不是類似於我們設計的高性能服務端架構通過緩存->業務邏輯->業務數據;只是這個業務邏輯是在數據庫領域的而已;

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

程序員的MySQL攻略,總結的非常全面系統

查詢流程

再看一下一個SQL的執行過程,SQL Cache->解析器->優化器->執行引擎->存儲引擎;是不是類似於我們設計的高性能服務端架構通過緩存->業務邏輯->業務數據;只是這個業務邏輯是在數據庫領域的而已;

程序員的MySQL攻略,總結的非常全面系統

事務

數據庫事務應該是大部分程序員在面試時的必經題目了,先一句話描述一下我所理解的事務:

在併發場景保障一次會話對數據操作符合預期(原子性、一致性、隔離性、持久性)的方式;

下面會分為名詞解釋和隔離級別兩趴來幫助我們理解事務;

名詞解釋

想象一下我們有多個客戶端(A/B/N)在並行的操作一張表T1中的數據,那麼就可能會存在如下幾種情況:

1、髒讀:A可能讀取到B會話中未提交事務修改的數據(不可預期的數據結果)

2、不可重複讀:一個事物內多次查詢同一數據行,結果是不一致

3、幻讀:範圍檢索時兩次檢索會看到不同的數據行(範圍檢索不僅限於大於小於,部分的in場景或者全表掃描一樣會被覆蓋)

在以上場景下,MySQL定義瞭如下四種隔離級別:

PS:默認隔離級別是Repeatable_Read

隔離級別

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

程序員的MySQL攻略,總結的非常全面系統

查詢流程

再看一下一個SQL的執行過程,SQL Cache->解析器->優化器->執行引擎->存儲引擎;是不是類似於我們設計的高性能服務端架構通過緩存->業務邏輯->業務數據;只是這個業務邏輯是在數據庫領域的而已;

程序員的MySQL攻略,總結的非常全面系統

事務

數據庫事務應該是大部分程序員在面試時的必經題目了,先一句話描述一下我所理解的事務:

在併發場景保障一次會話對數據操作符合預期(原子性、一致性、隔離性、持久性)的方式;

下面會分為名詞解釋和隔離級別兩趴來幫助我們理解事務;

名詞解釋

想象一下我們有多個客戶端(A/B/N)在並行的操作一張表T1中的數據,那麼就可能會存在如下幾種情況:

1、髒讀:A可能讀取到B會話中未提交事務修改的數據(不可預期的數據結果)

2、不可重複讀:一個事物內多次查詢同一數據行,結果是不一致

3、幻讀:範圍檢索時兩次檢索會看到不同的數據行(範圍檢索不僅限於大於小於,部分的in場景或者全表掃描一樣會被覆蓋)

在以上場景下,MySQL定義瞭如下四種隔離級別:

PS:默認隔離級別是Repeatable_Read

隔離級別

程序員的MySQL攻略,總結的非常全面系統

敲重點:

面試必考題:

1、MySQL事務的的隔離級別及其特性

2、解釋一下來髒讀、不可重複讀、幻讀的含義及其出現的場景 能夠很好的回答以上問題,在MySQL事務單項上就及格了;

進階:

1、數據庫默認的隔離級別是什麼?你們線上數據庫用的是哪個級別?為什麼選擇這個級別?

2、MySQL RR 級別是如何解決不可重複讀?

3、MySQL RR 級別是否解決了幻讀?

想回答好進階問題,就要對MySQL的鎖 & MVCC有一定的瞭解了

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

程序員的MySQL攻略,總結的非常全面系統

查詢流程

再看一下一個SQL的執行過程,SQL Cache->解析器->優化器->執行引擎->存儲引擎;是不是類似於我們設計的高性能服務端架構通過緩存->業務邏輯->業務數據;只是這個業務邏輯是在數據庫領域的而已;

程序員的MySQL攻略,總結的非常全面系統

事務

數據庫事務應該是大部分程序員在面試時的必經題目了,先一句話描述一下我所理解的事務:

在併發場景保障一次會話對數據操作符合預期(原子性、一致性、隔離性、持久性)的方式;

下面會分為名詞解釋和隔離級別兩趴來幫助我們理解事務;

名詞解釋

想象一下我們有多個客戶端(A/B/N)在並行的操作一張表T1中的數據,那麼就可能會存在如下幾種情況:

1、髒讀:A可能讀取到B會話中未提交事務修改的數據(不可預期的數據結果)

2、不可重複讀:一個事物內多次查詢同一數據行,結果是不一致

3、幻讀:範圍檢索時兩次檢索會看到不同的數據行(範圍檢索不僅限於大於小於,部分的in場景或者全表掃描一樣會被覆蓋)

在以上場景下,MySQL定義瞭如下四種隔離級別:

PS:默認隔離級別是Repeatable_Read

隔離級別

程序員的MySQL攻略,總結的非常全面系統

敲重點:

面試必考題:

1、MySQL事務的的隔離級別及其特性

2、解釋一下來髒讀、不可重複讀、幻讀的含義及其出現的場景 能夠很好的回答以上問題,在MySQL事務單項上就及格了;

進階:

1、數據庫默認的隔離級別是什麼?你們線上數據庫用的是哪個級別?為什麼選擇這個級別?

2、MySQL RR 級別是如何解決不可重複讀?

3、MySQL RR 級別是否解決了幻讀?

想回答好進階問題,就要對MySQL的鎖 & MVCC有一定的瞭解了

程序員的MySQL攻略,總結的非常全面系統

鎖 & MVCC

鎖是併發場景下解決共享資源操作衝突問題的常見手段,同理MySQL也採用了該種策略,下面會分別介紹一下MySQL的鎖

在正式介紹之前補充一點背景信息,對於MySQL而言,讀分為快照讀和當前讀,

快照讀:select * from t1 where ;

當前讀:select xxx lock in share mode;select xxx for

update;insert/update/delete xxx;

鎖類型

表鎖

表鎖字義是對標進行加鎖,特點是開銷小,加鎖快,併發度低; MYISAM 引擎僅支持表鎖

在innodb引擎寫操作中兩種意向鎖(意向共享鎖和意向排他鎖)也是一種表鎖;

頁鎖

BDB引擎支持的鎖類型,引擎和相關資料都比較少,鎖粒度介於行和表之間

行鎖

1、行鎖和字面意思有一點區別,主要是區分於Oracle數據庫的行鎖是針對物理數據塊進行加鎖,而MySQL是針對索引進行加鎖的,也就意味著只有走索引才能加行鎖否則在需要加鎖的場景下就是表鎖

2、行鎖開銷大、加鎖慢、併發度高(衝突概率低)

3、行鎖同樣分為共享鎖和排他鎖

間隙鎖

間隙鎖是在RR級別下生效,在當前讀場景下會鎖定索引間的間隙,保證索引間的記錄不變;以防止插入或更新間隙之間的記錄;

而RR級別下的間隙鎖也就部分解決了幻讀的問題

nextKey lock

等於 行鎖+間隙鎖

鎖衝突表

. IX IS X S IX 兼容 兼容 衝突 衝突 IS 兼容 兼容 衝突 兼容 X 衝突 衝突 衝突 衝突 S 衝突 兼容 衝突 兼容 MVCC

MVCC翻譯過來是多版本併發控制;在RC和RR級別下生效,就是解決上面所提到不同隔離級別下的不可重複讀和幻讀的問題;

我們假設自己來來實現這個效果,一般的思路是不是在一個事物開啟的時候

1、通過記錄當前記錄的快照,在事物結束之前一直讀該快照來保障單次事物內結果是可預期的;

2、再加上鎖來阻止其他併發更新

思路是正確的但是MySQL對快照的處理上不像我們想象的一樣真的插入一條記錄而是通過undo_log+readview的機制來實現的

數據結構

innodb引擎在數據中增加了

事務號DB_TRX_ID(創建、更新、刪除)

回滾段指針DB_ROLL_PTR(用於追溯歷史版本數據)

DB_ROW_ID(隨著新行插入而單調遞增的行ID)

undo_log

insert/update/delete時會產生undo log

undo log中包含重建該行記錄被更新之前內容

readview

RC:事務中每條select語句都會創建一個快照(read view);

RR:事務在begin/start transaction之後的第一條select讀操作後, 會創建一個快照(read view), 將當前系統中活躍的其他事務記錄記錄起來 而這個區分也就決定了RR和RC兩個級別下可見性的區別;

補充說明一下,有一種說法是幻讀在當前讀場景下是解決了; 但是在快照讀的場景下還是還是存在對方已經提交但是在當前session讀不出來該數據,所以是部分解決了(對細節感興趣的話可以開兩個session 自行驗證一下);

索引

根據最上面的MySQL的體系架構圖可以得知數據最終是存儲在硬盤文件系統中的,計算機體系中硬盤數據是訪問最慢的,但是受限於內存數據的空間,在這種約束下通過針對具體業務場景,對高頻數據訪問場景通過增加索引的方式提高數據訪問效率

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

程序員的MySQL攻略,總結的非常全面系統

查詢流程

再看一下一個SQL的執行過程,SQL Cache->解析器->優化器->執行引擎->存儲引擎;是不是類似於我們設計的高性能服務端架構通過緩存->業務邏輯->業務數據;只是這個業務邏輯是在數據庫領域的而已;

程序員的MySQL攻略,總結的非常全面系統

事務

數據庫事務應該是大部分程序員在面試時的必經題目了,先一句話描述一下我所理解的事務:

在併發場景保障一次會話對數據操作符合預期(原子性、一致性、隔離性、持久性)的方式;

下面會分為名詞解釋和隔離級別兩趴來幫助我們理解事務;

名詞解釋

想象一下我們有多個客戶端(A/B/N)在並行的操作一張表T1中的數據,那麼就可能會存在如下幾種情況:

1、髒讀:A可能讀取到B會話中未提交事務修改的數據(不可預期的數據結果)

2、不可重複讀:一個事物內多次查詢同一數據行,結果是不一致

3、幻讀:範圍檢索時兩次檢索會看到不同的數據行(範圍檢索不僅限於大於小於,部分的in場景或者全表掃描一樣會被覆蓋)

在以上場景下,MySQL定義瞭如下四種隔離級別:

PS:默認隔離級別是Repeatable_Read

隔離級別

程序員的MySQL攻略,總結的非常全面系統

敲重點:

面試必考題:

1、MySQL事務的的隔離級別及其特性

2、解釋一下來髒讀、不可重複讀、幻讀的含義及其出現的場景 能夠很好的回答以上問題,在MySQL事務單項上就及格了;

進階:

1、數據庫默認的隔離級別是什麼?你們線上數據庫用的是哪個級別?為什麼選擇這個級別?

2、MySQL RR 級別是如何解決不可重複讀?

3、MySQL RR 級別是否解決了幻讀?

想回答好進階問題,就要對MySQL的鎖 & MVCC有一定的瞭解了

程序員的MySQL攻略,總結的非常全面系統

鎖 & MVCC

鎖是併發場景下解決共享資源操作衝突問題的常見手段,同理MySQL也採用了該種策略,下面會分別介紹一下MySQL的鎖

在正式介紹之前補充一點背景信息,對於MySQL而言,讀分為快照讀和當前讀,

快照讀:select * from t1 where ;

當前讀:select xxx lock in share mode;select xxx for

update;insert/update/delete xxx;

鎖類型

表鎖

表鎖字義是對標進行加鎖,特點是開銷小,加鎖快,併發度低; MYISAM 引擎僅支持表鎖

在innodb引擎寫操作中兩種意向鎖(意向共享鎖和意向排他鎖)也是一種表鎖;

頁鎖

BDB引擎支持的鎖類型,引擎和相關資料都比較少,鎖粒度介於行和表之間

行鎖

1、行鎖和字面意思有一點區別,主要是區分於Oracle數據庫的行鎖是針對物理數據塊進行加鎖,而MySQL是針對索引進行加鎖的,也就意味著只有走索引才能加行鎖否則在需要加鎖的場景下就是表鎖

2、行鎖開銷大、加鎖慢、併發度高(衝突概率低)

3、行鎖同樣分為共享鎖和排他鎖

間隙鎖

間隙鎖是在RR級別下生效,在當前讀場景下會鎖定索引間的間隙,保證索引間的記錄不變;以防止插入或更新間隙之間的記錄;

而RR級別下的間隙鎖也就部分解決了幻讀的問題

nextKey lock

等於 行鎖+間隙鎖

鎖衝突表

. IX IS X S IX 兼容 兼容 衝突 衝突 IS 兼容 兼容 衝突 兼容 X 衝突 衝突 衝突 衝突 S 衝突 兼容 衝突 兼容 MVCC

MVCC翻譯過來是多版本併發控制;在RC和RR級別下生效,就是解決上面所提到不同隔離級別下的不可重複讀和幻讀的問題;

我們假設自己來來實現這個效果,一般的思路是不是在一個事物開啟的時候

1、通過記錄當前記錄的快照,在事物結束之前一直讀該快照來保障單次事物內結果是可預期的;

2、再加上鎖來阻止其他併發更新

思路是正確的但是MySQL對快照的處理上不像我們想象的一樣真的插入一條記錄而是通過undo_log+readview的機制來實現的

數據結構

innodb引擎在數據中增加了

事務號DB_TRX_ID(創建、更新、刪除)

回滾段指針DB_ROLL_PTR(用於追溯歷史版本數據)

DB_ROW_ID(隨著新行插入而單調遞增的行ID)

undo_log

insert/update/delete時會產生undo log

undo log中包含重建該行記錄被更新之前內容

readview

RC:事務中每條select語句都會創建一個快照(read view);

RR:事務在begin/start transaction之後的第一條select讀操作後, 會創建一個快照(read view), 將當前系統中活躍的其他事務記錄記錄起來 而這個區分也就決定了RR和RC兩個級別下可見性的區別;

補充說明一下,有一種說法是幻讀在當前讀場景下是解決了; 但是在快照讀的場景下還是還是存在對方已經提交但是在當前session讀不出來該數據,所以是部分解決了(對細節感興趣的話可以開兩個session 自行驗證一下);

索引

根據最上面的MySQL的體系架構圖可以得知數據最終是存儲在硬盤文件系統中的,計算機體系中硬盤數據是訪問最慢的,但是受限於內存數據的空間,在這種約束下通過針對具體業務場景,對高頻數據訪問場景通過增加索引的方式提高數據訪問效率

程序員的MySQL攻略,總結的非常全面系統

索引類型

聚簇索引

以主鍵創建的索引

1、聚集索引在葉子節點存儲的是表中的數據

非聚簇索引(二級索引)

非主鍵創建的索引

1、索引葉子節點存儲的是主鍵和索引列

2、在檢索列中包含非索引列時,需要用葉子節點的主鍵,再去表中檢索其他列(回表)

索引結構

數據結構應該都不陌生,而索引就是通過不同數據結構的特性:查詢複雜度、空間、查詢和新增性能等來做出的選擇;

在一個海量數據的場景下我們想要保障查詢的效率很直接的一種方式就是根據構建hash表;

另外一種相對可控的就是樹形結構可以通過控制樹的深度來保證查詢的效率;

B+ tree

它是一個矮胖子;左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹;

這樣的結構保障了查詢效率的相對高效和穩定;

但是我們看一下在更新和新增場景下由於要維持以上特性,需要進行分裂或合併,這樣對插入性能來說是有一定損失的;

Hash表

hash表的好處是查詢複雜度理論值是o(1),,但是帶來的問題如下

1、空間的消耗

2、不支持範圍和區間查詢

3、大數據量場景下的hash衝突,可能會導致退化成鏈表

在目前的MySQL版本中hash索引是MySQL自適應的無法干預

匹配原則

基於以上索引的設計可以看出,可以分析出在索引使用的過程中有如下特點

一個表可能創建多個索引

一次只能走一個索引

最左匹配

索引選擇上根據 where 條件中的列字段,從左至右的匹配,直到遇到區間或範圍查詢列;

注意此處和SQL中where 後 in、=條件的列字段順序無關;

查詢列不參與計算

如果對列字段添加了計算函數,則無法走該字段的索引

where 和 order by limit 場景下的索引

在存在where 和 order by的場景下,本以為會按照where條件走索引,但是在實際情況下可能會發現最終索引是order by 字段,優先選擇order by字段索引;

原因是:limit存在時,查詢的順序就有可能發生變化,查詢過程不是先通過where過濾再排序再limit而是根據order by索引反向取進而然後匹配where 條件看看是否滿足,有點類似於全表掃描了;

性能

即使是知道了以上各種原則,但在實際過程中還是可能遇到不符合預期的情況,這時就需要MySQL提供的debug利器執行計劃了

執行計劃

"

前言:大部分業務研發同學在工作的90%的場景下會和各種數據打交道,在此過程中邁不過去的一個坎就是MySQL了,這篇文章從研發同學的視角來講述在MySQL使用中需要了解的各種關鍵技術;

下面我會分別從MySQL的體系架構、事務、鎖、索引、性能、部署架構幾個方面來介紹; 非特殊註明的情況下專指innodb引擎,希望各位在看完之後能夠有所收穫!

程序員的MySQL攻略,總結的非常全面系統


體系架構

想要了解一個技術體系非常建議的一種方式是先看系統整體的架構設計,這樣能夠快速的預覽整個框架,降低陌生感;然後通過分析一個典型的執行過程增強對過程的把控;

整體框架

在MySQL的設計中整體可以分為三層:文件系統、存儲(索引)、服務層;我們所直接面向主要是服務層相關的模塊如:連接池、SQL、優化器、緩存等,可以通過下圖對MySQL的組成有個大概的瞭解

程序員的MySQL攻略,總結的非常全面系統

查詢流程

再看一下一個SQL的執行過程,SQL Cache->解析器->優化器->執行引擎->存儲引擎;是不是類似於我們設計的高性能服務端架構通過緩存->業務邏輯->業務數據;只是這個業務邏輯是在數據庫領域的而已;

程序員的MySQL攻略,總結的非常全面系統

事務

數據庫事務應該是大部分程序員在面試時的必經題目了,先一句話描述一下我所理解的事務:

在併發場景保障一次會話對數據操作符合預期(原子性、一致性、隔離性、持久性)的方式;

下面會分為名詞解釋和隔離級別兩趴來幫助我們理解事務;

名詞解釋

想象一下我們有多個客戶端(A/B/N)在並行的操作一張表T1中的數據,那麼就可能會存在如下幾種情況:

1、髒讀:A可能讀取到B會話中未提交事務修改的數據(不可預期的數據結果)

2、不可重複讀:一個事物內多次查詢同一數據行,結果是不一致

3、幻讀:範圍檢索時兩次檢索會看到不同的數據行(範圍檢索不僅限於大於小於,部分的in場景或者全表掃描一樣會被覆蓋)

在以上場景下,MySQL定義瞭如下四種隔離級別:

PS:默認隔離級別是Repeatable_Read

隔離級別

程序員的MySQL攻略,總結的非常全面系統

敲重點:

面試必考題:

1、MySQL事務的的隔離級別及其特性

2、解釋一下來髒讀、不可重複讀、幻讀的含義及其出現的場景 能夠很好的回答以上問題,在MySQL事務單項上就及格了;

進階:

1、數據庫默認的隔離級別是什麼?你們線上數據庫用的是哪個級別?為什麼選擇這個級別?

2、MySQL RR 級別是如何解決不可重複讀?

3、MySQL RR 級別是否解決了幻讀?

想回答好進階問題,就要對MySQL的鎖 & MVCC有一定的瞭解了

程序員的MySQL攻略,總結的非常全面系統

鎖 & MVCC

鎖是併發場景下解決共享資源操作衝突問題的常見手段,同理MySQL也採用了該種策略,下面會分別介紹一下MySQL的鎖

在正式介紹之前補充一點背景信息,對於MySQL而言,讀分為快照讀和當前讀,

快照讀:select * from t1 where ;

當前讀:select xxx lock in share mode;select xxx for

update;insert/update/delete xxx;

鎖類型

表鎖

表鎖字義是對標進行加鎖,特點是開銷小,加鎖快,併發度低; MYISAM 引擎僅支持表鎖

在innodb引擎寫操作中兩種意向鎖(意向共享鎖和意向排他鎖)也是一種表鎖;

頁鎖

BDB引擎支持的鎖類型,引擎和相關資料都比較少,鎖粒度介於行和表之間

行鎖

1、行鎖和字面意思有一點區別,主要是區分於Oracle數據庫的行鎖是針對物理數據塊進行加鎖,而MySQL是針對索引進行加鎖的,也就意味著只有走索引才能加行鎖否則在需要加鎖的場景下就是表鎖

2、行鎖開銷大、加鎖慢、併發度高(衝突概率低)

3、行鎖同樣分為共享鎖和排他鎖

間隙鎖

間隙鎖是在RR級別下生效,在當前讀場景下會鎖定索引間的間隙,保證索引間的記錄不變;以防止插入或更新間隙之間的記錄;

而RR級別下的間隙鎖也就部分解決了幻讀的問題

nextKey lock

等於 行鎖+間隙鎖

鎖衝突表

. IX IS X S IX 兼容 兼容 衝突 衝突 IS 兼容 兼容 衝突 兼容 X 衝突 衝突 衝突 衝突 S 衝突 兼容 衝突 兼容 MVCC

MVCC翻譯過來是多版本併發控制;在RC和RR級別下生效,就是解決上面所提到不同隔離級別下的不可重複讀和幻讀的問題;

我們假設自己來來實現這個效果,一般的思路是不是在一個事物開啟的時候

1、通過記錄當前記錄的快照,在事物結束之前一直讀該快照來保障單次事物內結果是可預期的;

2、再加上鎖來阻止其他併發更新

思路是正確的但是MySQL對快照的處理上不像我們想象的一樣真的插入一條記錄而是通過undo_log+readview的機制來實現的

數據結構

innodb引擎在數據中增加了

事務號DB_TRX_ID(創建、更新、刪除)

回滾段指針DB_ROLL_PTR(用於追溯歷史版本數據)

DB_ROW_ID(隨著新行插入而單調遞增的行ID)

undo_log

insert/update/delete時會產生undo log

undo log中包含重建該行記錄被更新之前內容

readview

RC:事務中每條select語句都會創建一個快照(read view);

RR:事務在begin/start transaction之後的第一條select讀操作後, 會創建一個快照(read view), 將當前系統中活躍的其他事務記錄記錄起來 而這個區分也就決定了RR和RC兩個級別下可見性的區別;

補充說明一下,有一種說法是幻讀在當前讀場景下是解決了; 但是在快照讀的場景下還是還是存在對方已經提交但是在當前session讀不出來該數據,所以是部分解決了(對細節感興趣的話可以開兩個session 自行驗證一下);

索引

根據最上面的MySQL的體系架構圖可以得知數據最終是存儲在硬盤文件系統中的,計算機體系中硬盤數據是訪問最慢的,但是受限於內存數據的空間,在這種約束下通過針對具體業務場景,對高頻數據訪問場景通過增加索引的方式提高數據訪問效率

程序員的MySQL攻略,總結的非常全面系統

索引類型

聚簇索引

以主鍵創建的索引

1、聚集索引在葉子節點存儲的是表中的數據

非聚簇索引(二級索引)

非主鍵創建的索引

1、索引葉子節點存儲的是主鍵和索引列

2、在檢索列中包含非索引列時,需要用葉子節點的主鍵,再去表中檢索其他列(回表)

索引結構

數據結構應該都不陌生,而索引就是通過不同數據結構的特性:查詢複雜度、空間、查詢和新增性能等來做出的選擇;

在一個海量數據的場景下我們想要保障查詢的效率很直接的一種方式就是根據構建hash表;

另外一種相對可控的就是樹形結構可以通過控制樹的深度來保證查詢的效率;

B+ tree

它是一個矮胖子;左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹;

這樣的結構保障了查詢效率的相對高效和穩定;

但是我們看一下在更新和新增場景下由於要維持以上特性,需要進行分裂或合併,這樣對插入性能來說是有一定損失的;

Hash表

hash表的好處是查詢複雜度理論值是o(1),,但是帶來的問題如下

1、空間的消耗

2、不支持範圍和區間查詢

3、大數據量場景下的hash衝突,可能會導致退化成鏈表

在目前的MySQL版本中hash索引是MySQL自適應的無法干預

匹配原則

基於以上索引的設計可以看出,可以分析出在索引使用的過程中有如下特點

一個表可能創建多個索引

一次只能走一個索引

最左匹配

索引選擇上根據 where 條件中的列字段,從左至右的匹配,直到遇到區間或範圍查詢列;

注意此處和SQL中where 後 in、=條件的列字段順序無關;

查詢列不參與計算

如果對列字段添加了計算函數,則無法走該字段的索引

where 和 order by limit 場景下的索引

在存在where 和 order by的場景下,本以為會按照where條件走索引,但是在實際情況下可能會發現最終索引是order by 字段,優先選擇order by字段索引;

原因是:limit存在時,查詢的順序就有可能發生變化,查詢過程不是先通過where過濾再排序再limit而是根據order by索引反向取進而然後匹配where 條件看看是否滿足,有點類似於全表掃描了;

性能

即使是知道了以上各種原則,但在實際過程中還是可能遇到不符合預期的情況,這時就需要MySQL提供的debug利器執行計劃了

執行計劃

程序員的MySQL攻略,總結的非常全面系統

type index: 掃描全部索引樹

range: 掃描部分索引,索引範圍掃描,對索引的掃描開始於某一點,返回匹配值域的行,常見於between、<、>等的查詢

ref: 非唯一性索引掃描,返回匹配某個單獨值的所有行。常見於使用非唯一索引即唯一索引的非唯一前綴進行的查找

eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描

const, system: 當MySQL對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量。system是const類型的特例,當查詢的表只有一行的情況下, 使用system。

NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引。

possible_keys:可選的索引列

key:當前選擇的索引列

ref:連接匹配條件,如果走主鍵索引的話,該值為: const, 全表掃描的話,為null值

rows:掃描行數

extra: using index表示在相應的select中使用了覆蓋索引。 usingwhere表示存儲引擎搜到記錄後進行了後過濾(POST-FILTER),如果查詢未能使用索引,usingwhere的作用只是提醒我們mysql要用where條件過濾z結果集。 using temporay表示用臨時表來存儲結果集,常見於排序和分組查詢。 usingfilesort,mysql中無法用索引完成的排序成為文件排序。

優化

索引區分度

選擇高區分度列

覆蓋索引:查詢列儘量包含在索引中,否則需要回表

SQL優化

大表翻頁:查詢列儘量是索引列,否則建議用join或子查詢的方式通過主鍵完成

樂觀鎖

select for update 和基於version的樂觀鎖,在極限衝突場景下到底哪種性能更高待驗證

數據量控制

分庫分表 冷熱數據分離

讀寫分離:備庫可以考慮承擔一部分讀流量

部署架構

物理或者邏輯架構的設計對於面向客戶提供的可靠性至關重要,作為數據的核心數據的不可丟失以及提供高性能的解決方案,從架構層面有一些設計方式;

主從

可靠性的一個重要保障方式就是做副本,一種經典的MySQL部署方式master-slave模式,部署兩個節點:master和slave;

master節點提供讀寫服務,通過解析binlog把數據變更復制到另外一臺slave節點;存在ms級的延時,在某種程度上保障了數據的物理隔離,降低單點故障帶來的損失;

分庫

分庫其實是一種邏輯上的架構,不過一般來說比較建議不同的邏輯庫可以散列分佈,來提高吞吐性能,在各個邏輯庫上又可以做主從架構,每一個節點做一個備份。

不管是分庫還是分表都要注意維度,按照業務場景來評估,儘量保證檢索場景覆蓋了拆分維度。

異地多活 & 多副本一致

傳統上而言主備都是在同地域甚至是同一個機房來降低同步延時,但是在一些極限場景下對數據的可用性以及吞吐量要求更高,這個時候跨地域的邏輯庫以及多副本的一致性架構就開始出現了,阿里巴巴電商交易在15年開始規劃跨地域數據解決方案,其中主要用到的策略

1、按router路由,保障同一用戶落在同一地域

2、跨地域的數據同步

3、同一sequence生產方式(集中式、分佈式)

當前基於最新分佈式一致協議(Paxos)構建的 多副本強一致方案也有落地

其他數據庫

瞭解一些其他類型的數據庫,在做技術選型和決策的時候可能會有所幫助,目前主流的大概是這些

關係型數據庫

MySQL/Oracle/PG/SQLServer 等

非關係型數據庫

Hbase/MongoDB/Cassandra/LevelDB/Redis等

圖數據庫

Neo4j/GraphDB等

end:如果你覺得本文對你有幫助的話,記得關注點贊轉發,你的支持就是我更新動力。

"

相關推薦

推薦中...