本文目錄:html
1、表空間加密概述mysql
- 應⽤場景
- 加密插件
- 加密限制
- 注意事項
2、加密表空間linux
- 安裝加密插件
- 配置表空間加密
- 查看錶空間被加密的表
3、更新 master encryption key
4、導⼊導出算法
- 案例
5、備份恢復sql
- innobackupex
6、參考文檔shell
從 5.7.11 開始,InnoDB 支持對獨立表空間進行靜態數據加密。該加密是在引擎內部數據頁級別的加密手段,在數據頁寫入文件系統時加密,從文件讀到內存中時解密,目前普遍使用的是 YaSSL/OpenSSL 提供的 AES 加密算法,加密先後數據頁大小不變,所以也稱爲透明加密。數據庫
它使用兩層加密密鑰架構,包括 master encryption key 和 tablespace key:vim
tablespace key 用於加密表空間文件。當訪問加密表空間時,後端
未配置表空間加密時,當發生相似拖庫操做時,數據很可能會泄漏。
配置表空間加密時,若是沒有加密時使用的 keyring(該文件由 keyring_file_data 參數設定),是讀取不到加密表空間數據的。因此當發生相似拖庫操做時,沒有相關的 keyring 文件時,數據基本不會泄漏的。這就要求存儲的 keyring 必定要嚴加保管,能夠採起如下措施來保存 keyring:安全
InnoDB 表空間加密依賴插件進行加密。企業版提供如下四種插件: keyring_file,keyring_encrypted_file,keyring_okv,keyring_aws。社區版目前只能使用 keyring_file 進行加密,本文僅介紹 keyring_file 插件:
1.AES 是惟一支持的加密算法。InnoDB 靜態表空間加密使用 Electronic Codebook (ECB) 加密模式來加密 tablespace key,使用 Cipher Block Chaining (CBC) 加密模式加密數據文件
2.ENCRYPTION 使用該 COPY 命令而不是 INPLACE 命令進行表空間的加密
3.僅支持對獨立表空間加密。不支持加密其餘表空間類型(如通用表空間和系統表空間)
4.不能將表從加密的獨立表空間移動或複製到不支持加密的表空間中
5.表空間加密僅對錶空間中的數據加密,不對 redo log,undo log,binary log 中的數據加密
6.不容許修改已加密的表的存儲引擎(修改成 innodb 存儲引擎則沒問題)
1.==在建立了第一個加密表空間、master encryption key 更新先後都必須立馬備份密鑰環文件。由於主加密密鑰丟失後,加密表空間中的數據將沒法恢復。 因此加密表時,必須採起措施防止主加密密鑰丟失,好比定時備份該文件#F44336 #F44336==
2.從安全角度考慮,不建議將密鑰環數據文件與表空間數據文件放在同一目錄下
3.若是數據庫在正常操做期間退出或中止,必定要使用一樣的加密配置來重啓數據庫,不然會致使之前加密的表空間沒法訪問
4.當第一次對錶空間加密時(不管是新表加密仍是舊錶加密),將生成第一個主加密密鑰。但對於運行的數據庫,移除 keyring 後,依舊能夠建立、讀寫加密表空間(但在數據庫重啓或更新 master encryption key 後這些操做會失敗)
5.更新 master encryption key 前需確保 keyring 文件存在,若是不存在,則會更新失敗,從而致使讀寫、建立加密表均失敗
6.僅當主從都配置了表空間加密,表空間加密操做纔可能在主從中均執行成功
如下的測試案例是在以下環境進行的:
1.必須先安裝並配置加密插件。在啓動數據庫時使用 early-plugin-load 選項來指定使用的加密插件,並使用 keyring_file_data 定義加密插件存放密鑰環文件的路徑
- 須要提早建立好相關目錄並調整權限,否則可能會報錯
2.只能使用一個加密插件,不能同時使用多個加密插件
3.一旦在 MySQL 實例中建立了加密表,後續重啓該實例時,必須給 early-plugin-load 指定建立加密表時使用的的加密插件。若是不這樣作,則在啓動服務器和InnoDB恢復期間會致使錯誤
4.必須配置獨立表空間:innodb_file_per_table=1
-- vim my.cnf,在 [mysqld] 下添加如下參數 [mysqld] early-plugin-load="keyring_file.so" keyring_file_data=/opt/mysql/keyring/3306/keyring innodb_file_per_table=1 -- 建立相關目錄及修改密鑰環文件所在目錄的權限 mkdir -p /opt/mysql/keyring/3306/ chown -R actiontech-universe:actiontech /opt/mysql/keyring/ chown -R actiontech-mysql:actiontech-mysql /opt/mysql/keyring/3306/ -- 查看插件是否加載 SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'keyring_file';
如下以 mydata.test_1 表來進行測試
/* 1. 爲新表加密 2. 插入數據至新表 3. 取消表加密 4. 開啓表加密 5. 查看加密表 */ mysql> CREATE TABLE mydata.test_1 (id INT primary key,age int) ENCRYPTION='Y'; Query OK, 0 rows affected (0.02 sec) mysql> insert into test_1 select 9,9; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE mydata.test_1 ENCRYPTION='N'; Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE mydata.test_1 ENCRYPTION='Y'; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table mydata.test_1;select * from mydata.test_1; +--------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +--------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ | test_1 | CREATE TABLE `test_1` ( `id` int(11) NOT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ENCRYPTION='Y' | +--------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.11 sec) +----+------+ | id | age | +----+------+ | 9 | 9 | +----+------+ 1 row in set (0.00 sec) /* 刪除當前的 keyring,使用備份的 keyring 恢復到原路徑並重啓,此時再查看 mydata.test_1 會查當作功。由於 mydata.test_1 加密解密用的 keyring 同樣 */ [root@localhost ~]# rm -rf /opt/mysql/keyring/3306/keyring [root@localhost ~]# mv /root/keyring /opt/mysql/keyring/3306/ [root@localhost ~]# systemctl restart mysqld_3306 [root@localhost ~]# mysql -h10.186.63.90 -uroot -p -P3306 -e"show create table mydata.test_1;select * from mydata.test_1;" Enter password: +--------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +--------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ | test_1 | CREATE TABLE `test_1` ( `id` int(11) NOT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ENCRYPTION='Y' | +--------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +----+------+ | id | age | +----+------+ | 9 | 9 | +----+------+
經過 ENCRYPTION 選項加密表空間時,表的加密信息會存放到 INFORMATION_SCHEMA.TABLES 的 CREATE_OPTIONS 字段中。因此能夠查詢該表來判斷表是否加密。
-- 查看加密的表: SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES WHERE CREATE_OPTIONS LIKE '%ENCRYPTION%'; -- 查看未加密的表: select concat(TABLE_SCHEMA,".",TABLE_NAME) from INFORMATION_SCHEMA.TABLES where (TABLE_SCHEMA,TABLE_NAME) not in (SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE CREATE_OPTIONS LIKE '%ENCRYPTION%' and table_schema not in ('information_schema','performance_schema','sys','mysql','universe')) and TABLE_SCHEMA in ('mydata');
應按期更換 master encryption key,或者懷疑 master encryption key 已經泄露時便須要更換了。
更新 master encryption key 只會改變 master encryption key 並從新加密 tablespace keys,不會解密或者從新加密表空間。
由於 tablespace_key 的明文不會變,更新 master_key 以後只須要把 tablespace_key 從新加密寫入第一個頁中便可。
master encryption key 的變動是一個原子的、實例級操做,每次變動 master encryption key 時,MySQL 實例中全部的 tablespace key 都會被從新加密並保存到各自的表空間頭部。由於是原子操做,因此一旦開始更新,對全部 tablespace keys 的從新加密必須所有成功;
-- 手動更新 master encryption key,成功後不影響加密表的使用 [root@localhost ~]# ll /opt/mysql/keyring/3306/keyring -rw-r----- 1 mysql mysql 155 Apr 19 02:05 /opt/mysql/keyring/3306/keyring [root@localhost ~]# mysql -h10.186.63.90 -uroot -p -P3306 -e"ALTER INSTANCE ROTATE INNODB MASTER KEY;" Enter password: [root@localhost ~]# ll /opt/mysql/keyring/3306/keyring -rw-r----- 1 mysql mysql 283 Apr 19 02:24 /opt/mysql/keyring/3306/keyring [root@localhost ~]# mysql -h10.186.63.90 -uroot -p -P3306 -e"select * from mydata.test_1;" Enter password: +----+------+ | id | age | +----+------+ | 9 | 9 | +----+------+
爲了支持 Export/Import 加密表,引入了 transfer_key,在 export 的時候隨機生成一個 transfer_key,把現有的 tablespace_key 用 transfer_key 加密,並將二者同時寫入 table_name.cfp 的文件中,注意這裏 transfer_key 保存的是明文。Import 會讀取 transfer_key 用來解密,而後執行正常的 import 操做便可,一旦 import 完成,table_name.cfg 文件會被馬上刪除:
導入導出流程以下:
1.目標庫:CREATE TABLE mydata.test_1 (id INT primary key,age int) ENCRYPTION='Y';,創建與源庫同名、同結構的表。
2.目標庫:ALTER TABLE test_1 DISCARD TABLESPACE;,此時會刪除 .ibd 文件
3.源庫:use test; FLUSH TABLES test_1 FOR EXPORT;,此時會產生 .cfg、.cfp 文件
4.目標庫:scp root@10.186.63.90:/opt/mysql/data/3306/mydata/test_1.{ibd,cfg.cfp} .
5.目標庫:chown actiontech-mysql:actiontech-mysql test_1*,複製文件後,須要修改用戶組及權限。
6.源庫:unlock tables;,此時會刪除 .cfg、.cfp 文件
7.目標庫:ALTER TABLE test_1 IMPORT TABLESPACE;,加載表 test_1
源庫:10.186.63.90:3306
目標庫:10.186.63.91:3307
# 在目標庫中創建與源庫同名、同結構的表 [root@localhost ~]# fg mysql -h10.186.63.91 -uroot -p -P3307 (wd: ~) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create database mydata; Query OK, 1 row affected (0.01 sec) mysql> CREATE TABLE mydata.test_1 (id INT primary key,age int) ENCRYPTION='Y'; Query OK, 0 rows affected (0.02 sec) # 目標庫執行 DISCARD TABLESPACE mysql> use mydata; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> ALTER TABLE test_1 DISCARD TABLESPACE; Query OK, 0 rows affected (0.02 sec) # 源庫執行 flush table ... fro export [root@localhost ~]# fg mysql -h10.186.63.90 -uroot -P3306 -p mysql> use mydata; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +------------------+ | Tables_in_mydata | +------------------+ | test_1 | +------------------+ 1 row in set (0.00 sec) mysql> FLUSH TABLES test_1 FOR EXPORT; Query OK, 0 rows affected (0.01 sec) mysql> [1]+ Stopped mysql -h10.186.63.90 -uroot -P3306 -p # 從源庫拷貝文件至目標庫 [root@localhost mydata]# scp root@10.186.63.90:/opt/mysql/data/3306/mydata/test_1.{ibd,cfg,cfp} . root@10.186.63.90's password: test_1.ibd 100% 96KB 41.0MB/s 00:00 root@10.186.63.90's password: test_1.cfg 100% 400 343.7KB/s 00:00 root@10.186.63.90's password: test_1.cfp 100% 100 132.7KB/s 00:00 [root@localhost mydata]# ll total 120 -rw-r----- 1 actiontech-mysql actiontech-mysql 67 Sep 28 05:49 db.opt -rw-r----- 1 root root 400 Sep 28 05:57 test_1.cfg -rw-r----- 1 root root 100 Sep 28 05:57 test_1.cfp -rw-r----- 1 actiontech-mysql actiontech-mysql 8584 Sep 28 05:50 test_1.frm -rw-r----- 1 root root 98304 Sep 28 05:57 test_1.ibd # 修改目標庫上文件的權限 [root@localhost mydata]# chown actiontech-mysql:actiontech-mysql * # 源庫上執行 unlock tables [root@localhost mydata]# fg mysql -h10.186.63.90 -uroot -P3306 -p (wd: ~) mysql> use mydata; Database changed mysql> unlock tables; Query OK, 0 rows affected (0.00 sec) # 目標庫上執行 ALTER TABLE ... IMPORT TABLESPACE; [root@localhost mydata]# fg mysql -h10.186.63.91 -uroot -p -P3307 (wd: ~) mysql> select * from mydata.test_1; ERROR 1814 (HY000): Tablespace has been discarded for table 'test_1' mysql> ALTER TABLE test_1 IMPORT TABLESPACE; Query OK, 0 rows affected (0.05 sec) mysql> select * from mydata.test_1; Empty set (0.00 sec)
參考文檔
mysqlbackup 備份恢復
innobackupex 備份恢復
mysqlbackup innobackupex 都可以對加密表空間進行加密,只不過須要注意版本:
這裏以 innobackupex 2.4.5 爲例進行加密表空間的備份恢復
innobackupex 備份加密表空間的注意事項:
innobackupex 不會複製密鑰環文件到備份目錄中,因此須要手動複製密鑰環文件到配置文件指定的 keyring-file-data 路徑
備份 10.186.63.90 中的數據至 10.186.63.91:3307
# 全量備份:加密表空間的全備的流程與常規的備份恢復基本同樣,只是須要額外指定一個參數:--keyring-file-data mkdir /data2/all_backup /data/urman-agent/bin/innobackupex --defaults-file=/opt/mysql/etc/3306/my.cnf --user=root --password=test -P3306 --socket=/opt/mysql/data/3306/mysqld.sock --parallel=8 --keyring-file-data=/opt/mysql/keyring/3306/keyring --no-timestamp /data2/all_backup # apply-log /data/urman-agent/bin/innobackupex --apply-log --keyring-file-data=/opt/mysql/keyring/3306/keyring /data2/all_backup/ # 複製全備文件、keyring 文件至目標庫 rm -rf /opt/mysql/data/3307/* && rm -rf /opt/mysql/keyring/3307/keyring && rm -rf /opt/mysql/log/redolog/3307/ib_logfile* scp -r /data2/all_backup/ root@10.186.63.91:/data2/ scp /opt/mysql/keyring/3306/keyring root@10.186.63.91:/opt/mysql/keyring/3307 # copy back /data/urman-agent//bin/innobackupex --defaults-file=/opt/mysql/etc/3307/my.cnf --copy-back --keyring-file-data=/opt/mysql/keyring/3307/keyring /data2/all_backup/ # 修改權限 chown actiontech-mysql:actiontech-mysql /opt/mysql/keyring/3307/keyring chown -R actiontech-mysql:actiontech-mysql /opt/mysql/data/3307/* chown -R actiontech-mysql:actiontech-mysql /opt/mysql/log/redolog/* # 啓動 systemctl start mysqld_3307
參考文檔
14.6.3.8 InnoDB Tablespace Encryption
InnoDB 表空間加密-原理篇