第10期:選擇合適的表空間

image

表空間的選擇,能夠說是對錶的平常管理以及訪問性能有很是緊密的聯繫。html

表空間是用來管理 MySQL 關係表的一種形式,有本身的磁盤文件。mysql

MySQL 表空間可分爲共享表空間單表空間;其中共享表空間又可分爲系統表空間通用表空間sql

下面我來逐一看下每種表空間的相關特性。數據庫

1、系統表空間

在 MySQL 數據目錄下有一個名爲 ibdata1 的文件,能夠保存一張或者多張表。性能

923275  12M -rw-r----- 1 mysql mysql  12M 3月  18 10:42 ibdata1

這個文件就是 MySQL 的系統表空間文件,默認爲 1 個,能夠有多個,只須要在配置文件 my.cnf 裏面這樣定義便可。優化

innodb_data_file_path=ibdata1:200M;ibdata2:200M:autoextend:max:800Mspa

系統表空間不只能夠是文件系統組成的文件,也能夠是非文件系統組成的磁盤塊,好比裸設備,定義也很簡單日誌

innodb_data_file_path=/dev/nvme0n1p1:3Gnewraw;/dev/nvme0n1p2:2Gnewrawcode

系統表空間裏都有些啥內容?

具體內容包括:double writer buffer、 change buffer、數據字典(MySQL 8.0 以前)、表數據、表索引。regexp

那 MySQL 爲何如今主流版本默認都不是系統表空間?

究其緣由,系統表空間有三個最大的缺點:

緣由 1:沒法作到自動收縮磁盤空間,形成很大的空間浪費。

即便它包含的表都被刪掉,這部分空間也不會自動釋放。

舉個例子:

# 表 t1
mysql> create table t1(id int, r1 char(36)) tablespace innodb_system;
Query OK, 0 rows affected (0.03 sec)

# ibdata1 初始大小爲 12M
mysql> \! ls -sihl ibdata1
923275 12M -rw-r----- 1 mysql mysql 12M 3月  18 15:32 ibdata1

# ... 插入一部分數據
# ...
mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
|   262144 |
+----------+
1 row in set (0.10 sec)

# ibdata1 增加到 76M
mysql> \! ls -sihl ibdata1
923275 76M -rw-r----- 1 mysql mysql 76M 3月  18 15:34 ibdata1

# 刪除這張表
mysql> drop table t1;
Query OK, 0 rows affected (0.02 sec)

# 空間並無釋放
mysql> \! ls -sihl ibdata1
923275 76M -rw-r----- 1 mysql mysql 76M 3月  18 15:39 ibdata1

如何才能釋放 ibdata1 呢?

這個比較麻煩,並且嚴重影響服務可用性,大體幾個步驟:

1.用 mysqldump 導出全部表數據;
2.關閉 MySQL 服務;
3.設置 ibdata1 爲默認大小;
4.source 從新導入數據。

緣由 2:擴容時,單表分離速度慢。

系統表空間在無限制增大致使磁盤滿須要擴容時,沒法快速的把表從系統表空間裏分離出來,必須得通過停服務;改配置;擴容;從新導入數據;啓服務等步驟方纔可行。

緣由 3:多張表的數據寫入順序寫。

對多張表的寫入數據依然是順序寫,這就導致 MySQL 發佈了單表空間來解決這兩個問題~

2、單表空間

單表空間不一樣於系統表空間,每一個表空間和表是一一對應的關係,每張表都有本身的表空間。具體在磁盤上表現爲後綴爲 .ibd 的文件。

好比表 t1,對應的表空間文件爲 t1.ibd

917107  96K -rw-r----- 1 mysql mysql  96K 3月  18 16:13 t1.ibd

單表空間如何應用到具體的表呢?

有兩種方式:

方式 1:在配置文件中開啓。

在配置文件中開啓單表空間設置參數 innodb_filer_per_table,這樣默認對當前庫下全部表開啓單表空間。

innodb_file_per_table=1

另外也能夠直接建表時指定單表空間

mysql> create table t1 (id int, r1 char(36)) tablespace innodb_file_per_table;
Query OK, 0 rows affected (0.04 sec)

單表空間除了解決以前說的系統表空間的幾個缺點外,還有其餘的優勢,詳細以下:

1.truncate table 操做比其餘的任何表空間都快;

2.能夠把不一樣的表按照使用場景指定在不一樣的磁盤目錄;

好比日誌表放在慢點的磁盤,把須要常常隨機讀的表放在 SSD 上等。

mysql> create table ytt_dedicated (id int) data directory = '/var/lib/mysql-files';
Query OK, 0 rows affected (0.04 sec)
  1. 能夠用 optimize table 來收縮或者重建常常增刪改查的表。

通常過程是這樣的:創建和原來表同樣的表結構和數據文件,把真實數據複製到臨時文件,再刪掉原始表定義和數據文件,最後把臨時文件的名字改成和原始表同樣的。

舉個例子,表 t1 以前的大小 324M

root@ytt-pc:/data/ytt/mysql/data/ytt# ls -sihl
總用量 325M
934068 4.0K -rw-r----- 1 mysql mysql   67 3月   6 23:01 db.opt
917593  12K -rw-r----- 1 mysql mysql 8.5K 3月  18 16:35 t1.frm
918181 325M -rw-r----- 1 mysql mysql 324M 3月  18 16:38 t1.ibd

進行表重建

mysql> optimize table t1;
+--------+----------+----------+-------------------------------------------------------------------+
| Table  | Op       | Msg_type | Msg_text                                                          |
+--------+----------+----------+-------------------------------------------------------------------+
| ytt.t1 | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| ytt.t1 | optimize | status   | OK                                                                |
+--------+----------+----------+-------------------------------------------------------------------+
2 rows in set (10.26 sec)

重建期間抓取到的結果:如願以償看到 # 開頭的臨時表定義和數據文件。

root@ytt-pc:/data/ytt/mysql/data/ytt# ls -sihl
總用量 409M
934068 4.0K -rw-r----- 1 mysql mysql   67 3月   6 23:01  db.opt
917100  12K -rw-r----- 1 mysql mysql 8.5K 3月  18 16:38 '#sql-1791_7.frm'
917107  85M -rw-r----- 1 mysql mysql  84M 3月  18 16:39 '#sql-ib51-975102565.ibd'
917593  12K -rw-r----- 1 mysql mysql 8.5K 3月  18 16:35  t1.frm
918181 325M -rw-r----- 1 mysql mysql 324M 3月  18 16:38  t1.ibd

重建完成,表 t1 實際佔用空間 84M

root@ytt-pc:/data/ytt/mysql/data/ytt# ls -sihl
總用量 85M
934068 4.0K -rw-r----- 1 mysql mysql   67 3月   6 23:01 db.opt
917100  12K -rw-r----- 1 mysql mysql 8.5K 3月  18 16:38 t1.frm
917107  85M -rw-r----- 1 mysql mysql  84M 3月  18 16:39 t1.ibd
root@ytt-pc:/data/ytt/mysql/data/ytt#

4.能夠自由移植單表

並不須要移植整個數據庫,能夠把單獨的表在各個實例之間靈活移植。

好比如今要把 ytt.t1 的數據移植到 ytt2.t1 裏。

mysql> create database ytt2;
Query OK, 1 row affected (0.01 sec)

mysql> use ytt2
Database changed

mysql> create table t1 like ytt.t1;
Query OK, 0 rows affected (0.05 sec)

#  進行表數據移植。
mysql> alter table t1 discard tablespace;
Query OK, 0 rows affected (0.02 sec)

root@ytt-pc:/data/ytt/mysql/data/ytt# cp -rfp /tmp/t1.ibd ../ytt2/

mysql> alter table t1 import tablespace;
Query OK, 0 rows affected (0.38 sec)

# 確認下數據是否一致。
mysql> select (select count(*) from ytt.t1) 'ytt.t1',(select count(*) from ytt2.t1) 'ytt2.t1';
+---------+---------+
| ytt.t1  | ytt2.t1 |
+---------+---------+
| 2097152 | 2097152 |
+---------+---------+
1 row in set (1.69 sec)

5.單表空間的表可使用 MySQL 的新特性;

好比表壓縮,大對象更優化的磁盤存儲等。

6.能夠更好的管理和監控單個表的狀態;

好比在 OS 層能夠看到表的大小。

7.能夠解除 InnoDB 系統表空間的大小限制;

InnoDB 一個表空間最大支持 64TB 數據(針對 16KB 的頁大小)。若是是系統表空間,整個實例都被這個限制,單表空間則是針對單個表有 64TB 大小限制。

固然了,單表空間也並非沒有缺點。好比:當多張表被大量的增刪改後,表空間會有必定的膨脹;相比系統表空間,打開表須要的文件描述符增多,浪費更多的內存。

3、通用表空間

通用表空間先是出如今 MySQL Cluster 裏,也就是 NDB 引擎。從 MySQL 5.7 引入到 InnoDB 引擎。通用表空間和系統表空間同樣,也是共享表空間。每一個表空間能夠包含一張或者多張表,也就是說通用表空間和表之間是一對多的關係。

mysql> create tablespace ts1 add datafile '/var/lib/mysql-files/ts1.ibd' engine innodb;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t1(id int,r1 datetime) tablespace ts1;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t2(id int,r1 datetime) tablespace ts1;
Query OK, 0 rows affected (0.03 sec)

mysql> create table t3(id int,r1 datetime) tablespace ts1;
Query OK, 0 rows affected (0.03 sec)

通用表空間實際上是介於系統表空間和單表空間之間的一種折中的方案。

  • 和系統表空間相似,不會自動收縮磁盤空間;
  • 和系統表空間相似,能夠重命名錶空間名字;
  • 和單表空間相似,能夠很方便把表空間文件定義在 MySQL 數據目錄以外;
  • 比單表空間佔用更少的文件描述符,可是又不能像單表空間那樣移植表空間。

幸運的是,能夠在這三個表空間裏隨便切換。不過要注意切換時間點,畢竟切換涉及到數據的遷移,相似 copy 文件對系統的影響。

# 表 t1 隨時切換各類表空間
mysql> alter table t1 tablespace innodb_file_per_table;
Query OK, 0 rows affected (14.15 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table t1 tablespace innodb_system;
Query OK, 0 rows affected (16.95 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table t1 tablespace ts1;
Query OK, 0 rows affected (13.98 sec)
Records: 0  Duplicates: 0  Warnings: 0

到本篇的末尾,再來看下三種表空間如何銷燬:

  • 系統表空間沒法銷燬,除非把裏面的內容所有剝離出來;
  • 單表空間若是表被刪掉了,表空間也就自動銷燬;或者是表被移植到其餘表空間,單表空間也自動銷燬。
  • 通用表空間須要引用他的表所有刪掉或者移植到其餘表空間,才能夠被成功刪除。
# 刪除表空間 ts2 失敗
mysql> drop tablespace ts2;
ERROR 3120 (HY000): Tablespace `ts2` is not empty.
mysql> show errors;
+-------+------+--------------------------------+
| Level | Code | Message                        |
+-------+------+--------------------------------+
| Error | 3120 | Tablespace `ts2` is not empty. |
+-------+------+--------------------------------+
1 row in set (0.00 sec)

# 查看數據字典表來進一步查看錶空間 ts2 被哪些表引用了

mysql>  select regexp_replace(a.name,'/.+','') dbname,regexp_replace(a.name,'.+/','') tablename from innodb_tables a, innodb_tablespaces b where a.space = b.space and b.name= 'ts2';
+--------+-----------+
| dbname | tablename |
+--------+-----------+
| ytt    | t4        |
+--------+-----------+
1 row in set (0.00 sec)

# 刪除對應的表或者轉到其餘的表空間。
mysql> alter table t4 tablespace innodb_file_per_table;
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0

# 刪除表空間 ts2。
mysql> drop tablespace ts2;
Query OK, 0 rows affected (0.02 sec)

本篇主要介紹了 MySQL 三種表空間:單表空間、系統表空間、通用表空間。並把它們的優缺點以及相關注意事項簡單進行了說明,但願你們在建表之初考慮好表空間的所屬問題。

image

相關文章
相關標籤/搜索