MySQL 5.7新特性之線上收縮undo表空間
1. MySQL 5.5時代的undo log
在MySQL5.5以及之前,大家會發現隨著資料庫上線時間越來越長,ibdata1檔案(即InnoDB的共享表空間,或者系統表空間)會越來越大,這會造成2個比較明顯的問題:
(1)磁碟剩餘空間越來越小,到後期往往要加磁碟;
(2)物理備份時間越來越長,備份檔案也越來越大。
這是怎麼回事呢?
原因除了資料量自然增長之外,在MySQL5.5以及之前,InnoDB的undo log也是存放在ibdata1裡面的。一旦出現大事務,這個大事務所使用的undo log佔用的空間就會一直在ibdata1裡面存在,即使這個事務已經關閉。
那麼問題來了,有辦法把上面說的空閒的undo log佔用的空間從ibdata1裡面清理掉嗎?答案是沒有直接的辦法,只能全庫匯出sql檔案,然後重新初始化mysql例項,再全庫匯入。
2. MySQL 5.6時代的undo log
MySQL 5.6增加了引數innodb_undo_directory、innodb_undo_logs和innodb_undo_tablespaces這3個引數,可以把undo log從ibdata1移出來單獨存放。
下面對這3個引數做一下解釋:
(1)innodb_undo_directory,指定單獨存放undo表空間的目錄,預設為.(即datadir),可以設定相對路徑或者絕對路徑。該引數例項初始化之後雖然不可直接改動,但是可以透過先停庫,修改配置檔案,然後移動undo表空間檔案的方式去修改該引數;
(2)innodb_undo_tablespaces,指定單獨存放的undo表空間個數,例如如果設定為3,則undo表空間為undo001、undo002、undo003,每個檔案初始大小預設為10M。該引數我們推薦設定為大於等於3,原因下文將解釋。該引數例項初始化之後不可改動;
(3)innodb_undo_logs,指定回滾段的個數(早期版本該引數名字是innodb_rollback_segments),預設128個。每個回滾段可同時支援1024個線上事務。這些回滾段會平均分佈到各個undo表空間中。該變數可以動態調整,但是物理上的回滾段不會減少,只是會控制用到的回滾段的個數。
實際使用方面,在初始化例項之前,我們只需要設定innodb_undo_tablespaces引數(建議大於等於3)即可將undo log設定到單獨的undo表空間中。如果需要將undo log放到更快的裝置上時,可以設定innodb_undo_directory引數,但是一般我們不這麼做,因為現在SSD非常普及。innodb_undo_logs可以預設為128不變。
3. MySQL 5.7時代的undo log
那麼問題又來了,undo log單獨拆出來後就能縮小了嗎?MySQL 5.7引入了新的引數,innodb_undo_log_truncate,開啟後可線上收縮拆分出來的undo表空間。在滿足以下2個條件下,undo表空間檔案可線上收縮:
(1)innodb_undo_tablespaces>=2。因為truncate undo表空間時,該檔案處於inactive狀態,如果只有1個undo表空間,那麼整個系統在此過程中將處於不可用狀態。為了儘可能降低truncate對系統的影響,建議將該引數最少設定為3;
(2)innodb_undo_logs>=35(預設128)。因為在MySQL 5.7中,第一個undo log永遠在系統表空間中,另外32個undo log分配給了臨時表空間,即ibtmp1,至少還有2個undo log才能保證2個undo表空間中每個裡面至少有1個undo log;
滿足以上2個條件後,把 innodb_undo_log_truncate 設定為ON即可開啟undo表空間的自動truncate,這還跟如下2個引數有關:
(1)innodb_max_undo_log_size,undo表空間檔案超過此值即標記為可收縮,預設1G,可線上修改;
(2)innodb_purge_rseg_truncate_frequency,指定purge操作被喚起多少次之後才釋放rollback segments。當undo表空間裡面的rollback segments被釋放時,undo表空間才會被truncate。由此可見,該引數越小,undo表空間被嘗試truncate的頻率越高。
4. MySQL 5.7的undo表空間的truncate示例
(1) 首先確保如下引數被正確設定:
# 為了實驗方便,我們減小該值
innodb_max_undo_log_size =
100
M
innodb_undo_log_truncate =
ON
innodb_undo_logs =
128
innodb_undo_tablespaces =
3
# 為了實驗方便,我們減小該值
innodb_purge_rseg_truncate_frequency =
10
(2) 建立表:
mysql> create table t1(
-
> id int primary key auto_increment,
-
> name varchar(
200
));
Query OK, 0 rows affected (0.13 sec)
(3)插入測試資料
mysql> insert
into
t1(name) values(repeat(
'a'
,
200
));
Query OK,
1
row affected (
0.01
sec)
mysql> insert
into
t1(name)
select
name from t1;
Query OK,
1
row affected (
0.00
sec)
Records
:
1
Duplicates:
Warnings:
mysql> insert
into
t1(name)
select
name from t1;
Query OK,
2
rows
affected (
0.01
sec)
Records
:
2
Duplicates:
Warnings:
mysql> insert
into
t1(name)
select
name from t1;
Query OK,
4
rows
affected (
0.00
sec)
Records
:
4
Duplicates:
Warnings:
...
mysql> insert
into
t1(name)
select
name from t1;
Query OK,
8388608
rows
affected (
2
min
11.31
sec)
Records
:
8388608
Duplicates:
Warnings:
這時undo表空間檔案大小如下,可以看到有一個undo檔案已經超過了100M:
-rw-r----- 1 mysql mysql 13M Feb 17 17:59 undo001 -rw-r----- 1 mysql mysql 128M Feb 17 17:59 undo002 -rw-r----- 1 mysql mysql 64M Feb 17 17:59 undo003
此時,為了,讓purge執行緒執行,可以執行幾個delete語句:
mysql> delete from t1 limit 1; Query OK, 1 row affected (0.00 sec) mysql> delete from t1 limit 1; Query OK, 1 row affected (0.00 sec) mysql> delete from t1 limit 1; Query OK, 1 row affected (0.00 sec) mysql> delete from t1 limit 1; Query OK, 1 row affected (0.00 sec)
再檢視undo檔案大小:
-rw-r----- 1 mysql mysql 13M Feb 17 18:05 undo001 -rw-r----- 1 mysql mysql 10M Feb 17 18:05 undo002 -rw-r----- 1 mysql mysql 64M Feb 17 18:05 undo003
可以看到,超過100M的undo檔案已經收縮到10M了。
姜老師補充 :周伯通同學介紹了MySQL 5.7中undo表空間的收縮問題,這個問題可謂歷史久遠,想當初MySQL 3.23.49版本不時的磁碟空間不足,undo也是罪魁禍首之一。感謝周伯通同學的分享,感恩MySQL 5.7對於此問題的修復。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31383567/viewspace-2215388/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql收縮共享表空間MySql
- MySQL 8.0.2 新特性 UNDO表空間管理的靈活性提升MySql
- Oracle 11g 新特性 -- 臨時表空間收縮(轉)(Oracle
- Oracle 19c 線上縮減 UNDO 表空間 容量Oracle
- MySQL 5.7 新特性 共享臨時表空間及臨時表改進MySql
- MySQL 5.7新支援--通用表空間實戰MySql
- oracle之臨時表空間的收縮Oracle
- 分析表空間空閒率並收縮表空間
- ORACLE線上切換undo表空間Oracle
- mysql共享表空間擴容,收縮,遷移MySql
- Oracle表空間收縮方案Oracle
- 自動undo表空間模式下切換新的undo表空間模式
- MySQL InnoDB Undo表空間配置MySql
- 【MySQL】5.7新特性之四MySql
- 【MySQL】5.7新特性之五MySql
- 【MySQL】5.7新特性之六MySql
- 【MySQL】5.7新特性之七MySql
- DB2_收縮表空間DB2
- MySQL8.0 · 引擎特性 · 關於undo表空間的一些新變化MySql
- 收縮表空間 for Oracle 10gOracle 10g
- MySQL 8.0表空間新特性簡單實驗MySql
- MySQL 5.7新特性MySql
- oracle空間收縮Oracle
- oracle undo 表空間Oracle
- 理解UNDO表空間
- 5.7 mysql的可傳輸表空間MySql
- 【RESIZE】Oracle收縮表空間主要命令Oracle
- 【UNDO】使用重建UNDO表空間方法解決UNDO表空間過大問題
- MySQL UNDO表空間獨立和截斷MySql
- oracle UNDO表空間一個bug——undo表空間快速擴充套件Oracle套件
- 表空間(資料檔案shrink)收縮示例
- Oracle效能優化:收縮臨時表空間Oracle優化
- 【Mysql】Mysql5.7新特性之-json儲存MySqlJSON
- 【Mysql】mysql5.7新特性之-sys schema的作用MySql
- 【Mysql】MySQL 5.7新特性之Generated Column(函式索引)MySql函式索引
- MySQL · 特性分析 · MySQL 5.7新特性系列一MySql
- Oracle undo 表空間管理Oracle
- oracle重建UNDO表空間Oracle