mysql實戰45講 43 使用分割槽表

2021-09-24 19:51:10 字數 4497 閱讀 9796

有些時候,一些公司的規範不允許使用分割槽表,分割槽表有什麼問題?

先建立乙個分割槽表

create table `t` (

`ftime` datetime not null,

`c` int(11) default null,

key (`ftime`)

) engine=innodb default charset=latin1

partition by range (year(ftime))

(partition p_2017 values less than (2017) engine = innodb,

partition p_2018 values less than (2018) engine = innodb,

partition p_2019 values less than (2019) engine = innodb,

partition p_others values less than maxvalue engine = innodb);

insert into t values('2017-4-1',1),('2018-4-1',1);

表t在磁碟上的檔案

-rw-rw---- 1 mysql mysql     8586 apr  3 09:33 t.frm

-rw-rw---- 1 mysql mysql 52 apr 3 09:33 t.par

-rw-rw---- 1 mysql mysql 114688 apr 3 09:33 t#p#p_2017.ibd

-rw-rw---- 1 mysql mysql 114688 apr 3 09:33 t#p#p_2018.ibd

-rw-rw---- 1 mysql mysql 114688 apr 3 09:33 t#p#p_2019.ibd

在表中插入2條記錄,按照分割槽定義規則,這2個記錄分別落在2個分割槽上,

這個分割槽表,包含了乙個.frm檔案,每個分割槽對應乙個ibd檔案

--對於engine層來說,這是4個表

--對於server層來說,這是1個表

分割槽表的引擎層行為

session a

session b

t1begin;

select * from t where ftime='2017-2-1' for update;

t2insert into t values('2018-2-1',1); (ok)

insert into t values('2017-12-1',1);(block)

error1205 (hy000): lock wait timeout exceeded; try restarting transaction

在初始化表t的時候,只插入了兩行資料,ftime的值分別是('2017-4-1',1),('2018-4-1',1),session a的select語句對索引ftime上這兩個記錄之間的間隙加了鎖,

如果乙個普通表的話,在t1時刻,在表t的索引上,間隙和加鎖狀態時應該是圖下

也就是說,('2017-4-1',1)和('2018-4-1',1)這兩個記錄之間的間隙是會被鎖住,那麼session b的兩條插入語句應該都要進入鎖等待狀態。

從實驗上面的效果可以看出,session b的第乙個insert語句是可以執行的,這是因為對於引擎來說,p_2018和p_2016是兩個不同的表,

也就是說2017-4-1的下乙個記錄並不是2018-4-1而是p_2018分割槽的supermum,所以在t1時刻,在表t的ftime索引上,間隙和加鎖的狀態如下

由於分割槽的規則,session  a的select語句其實只操作了分割槽p_2018,因此加鎖的範圍就是上圖綠色的部分。

所以,session b要寫入一行ftime是2018-2-1的時候是成功的,而要寫入2017-12-1就這記錄就會等待session a的間隙鎖。

下面看myisam分割槽表的例子

用alter table t engine=myisam; 把t表的引擎改為myisam

session a

session b

alter table t engine=myisam;

update t set c=sleep(100) where ftime=』2017-4-1』;

select * from t where ftime=』2018-4-1』;

select * from t where ftime=』2017-5-1』;(block)

在session a裡面,用sleep(100)將這個語句的執行時間設定為100秒,由於myisam引擎只支援表鎖,這個update將會鎖主t表的讀鎖,從結果看,

session b的第一條是可以正常執行的,第二個才進入鎖等待狀態,這是因為myisam的表鎖是引擎層實現,session a加的表鎖,是在分割槽p_2018上面,因此只會堵塞在這個分割槽上執行的查詢操作。

手動分表和分割槽的差別

分割槽表和手工分表,乙個是由server層來決定使用哪個分割槽,乙個是由應用層**來決定使用哪個分表,因此,從引擎層來看,這兩種方式是沒有差別的。

其實這兩個方案的區別,主要是在server層上,從server層看,不得不提到乙個分割槽的問題:開啟表的行為

每當第一次訪問乙個分割槽表的時候,mysql需要把所有的分割槽有訪問一遍,乙個典型的報錯情況是這樣的,如果乙個分割槽表的分割槽很多,比如超過了1000個,而mysql啟動的時候,

open_files_limit引數使用的是預設值1024,那麼就會在訪問這個表的時候,由於需要開啟所有的檔案,導致開啟表檔案的個數超過了上限而報錯。

--insert to t_myisam values(『2017-4-1』,1);

--error1016 ,too many open files;

這個表是myisam引擎,如果使用innodb引擎的話,並不會出現這個問題。

myisam分割槽表使用的分割槽策略,稱為通用分割槽策略,每次訪問分割槽都由server層控制,通用分割槽策略,是mysql一開始支援分割槽表的行為,在檔案管理、表管理的實現上很粗糙,因此有比較嚴重的效能問題。

從mysql5.7.9開始,innodb引擎引入了本地分割槽策略,這個策略是在innodb內部自己管理開啟分割槽的行為。

mysql 從5.7.17開始,將myisam分割槽表標記為棄用,從8.0版本開始,myisam不允許建立分割槽表。

從server層看的話,分割槽表就只是乙個表

session a

session b

begin;

select * from t where ftime=』2018-4-1』;

alter table t truncate partition p_2017;(block)

--分割槽表的mdl鎖

可以看到,雖然session b只操作了分割槽p-2017,但是由於sesion a持有整個表的mdl鎖,就導致了session b的alter語句被堵住。

分割槽表,在做ddl的時候,影響會更大,如果使用的是普通分表,那麼在truncate分表的時候,肯定不會跟另外乙個分表上的查詢語句,出現mdl鎖衝突。

小結一下:

--1 mysql在第一次開啟分割槽表的時候,需要訪問所有的分割槽

--2 在server層,認為這是同乙個表,因此所有分割槽公用乙個mdl鎖

--3 在engine層,認為這是不同的表,因此mdl鎖之後的執行過程,會根據分割槽表規則,只訪問必要的分割槽。

而關於」必要的分割槽」的判斷,就是根據sql中的where條件,結合分割槽規則來實現,where ftime=』2017-4-1』。但是如果這個條件修改為where ftime>=』2017-4-1』,那麼就會訪問多個分割槽。

如果查詢語句的where條件彙總沒有分割槽key,那麼就要掃瞄整個分割槽了,所以在使用業務分割槽表的時候,where條件中必須要使用分割槽的key。

分割槽表的應用場景

分割槽表的乙個顯而易見的優勢是對業務透明,相對於使用者分表來說,使用分割槽表的業務**更簡潔,還有,分割槽表可以很方便的清理歷史資料。

如果一項業務跑的時間足夠長,往往就會有根據時間刪除歷史資料的需求,這時候,按照時間分割槽的分割槽表,就可以直接通過alter table t drop partition,這個語法刪除分割槽,從而刪掉過期的歷史資料。與普通表的drop類似。

--引數innodb_open_files,在innodb開啟檔案超過這個引數的值,就會掉一些之前開啟的檔案。

--引數open_files_limit,mysql開啟檔案的數量限制。

實戰mysql45講 MySQL實戰45講

作者簡介 林曉斌,網名 丁奇 前阿里資深技術專家,曾負責阿里雲rds核心開發團隊和運維團隊,並推動了alisql分支開源。作為活躍的mysql社群貢獻者,丁奇專注於資料儲存系統 mysql原始碼研究和改進 mysql效能優化和功能改進,熱衷於解決mysql疑難問題。課程亮點 你將獲得 前阿里資深技術...

mysql實戰45講筆記 07

07 行鎖功過 怎麼減少行鎖對效能的影響 mysql的行鎖是在引擎層由各個引擎自己實現的,不是所有資料庫都支援行鎖比如myisam 行鎖就是針對資料表中行記錄的鎖。在innodb事務中,行鎖是在需要的時候才加上的,但並不是不需要了就立刻回訪,而是等到事務結束時才釋放,這就是兩階段鎖協議。因此,如果事...

最新MySQL實戰45講教程

目錄 01.基礎架構 一條sql查詢語句是如何執行的?html 01.基礎架構 一條sql查詢語句是如何執行的?01.基礎架構 一條sql查詢語句是如何執行的?pdf 02.日誌系統 一條sql更新語句是如何執行的?html 02.日誌系統 一條sql更新語句是如何執行的?02.日誌系統 一條sql...