MySQL 8.0 表空间加密必须启用 keyring_file 插件,且需在 my.cnf 中配置 early-plugin-load 和 keyring_file_data 路径;主密钥须手动预置并验证,加密表仅支持独立表空间、不可降级为非加密,备份时密钥文件必须与数据文件一同归档。

MySQL 8.0 表空间加密必须启用 keyring_file 插件
MySQL 的 InnoDB 表空间加密(ENCRYPTION='Y')不是开箱即用的功能,它依赖外部密钥管理插件。在单机开发或测试环境,keyring_file 是唯一轻量、无需额外服务的选项;生产环境应改用 keyring_okv 或 keyring_aws,但配置复杂度陡增。不加载该插件就直接建加密表,会报错:ERROR 3182 (HY000): Cannot encrypt a table when the keyring plugin is not installed。
启用前确认 MySQL 版本 ≥ 8.0.13(早期 8.0.x 存在 keyring_file 写入权限 bug),且实例未启用 secure_file_priv 限制(否则插件无法写入密钥文件)。
- 插件路径通常为
plugin_dir下的keyring_file.so(Linux)或keyring_file.dll(Windows),可用SELECT @@plugin_dir;查看 - 插件加载命令必须在 MySQL 启动时完成,仅执行
INSTALL PLUGIN不持久——重启后失效 - 务必在
my.cnf的[mysqld]段落中添加两行:
early-plugin-load=keyring_file.so keyring_file_data=/var/lib/mysql-keyring/keyring
keyring_file_data 路径需由 MySQL 进程用户(如 mysql)可读写,且目录必须提前创建(mkdir -p /var/lib/mysql-keyring && chown mysql:mysql /var/lib/mysql-keyring)。路径不能是 /tmp 或符号链接——插件会拒绝加载。
主密钥生成与验证:别依赖默认密钥
MySQL 启动时若发现 keyring_file_data 文件不存在,会自动创建并写入一个随机主密钥(Master Key),但这个密钥不可控、不可备份、不可迁移。一旦密钥文件损坏或误删,所有加密表将永久无法访问——InnoDB 不会报错,但查询返回空或乱码,且 SHOW CREATE TABLE 中仍显示 ENCRYPTION='Y',极具迷惑性。
正确做法是手动预置主密钥。使用 OpenSSL 生成 32 字节 AES 密钥(对应 AES-256):
openssl rand -hex 32 > /var/lib/mysql-keyring/master.key
然后在启动前,将该密钥内容写入 keyring_file_data 文件(JSON 格式,注意换行和引号):
{
"key": "a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef",
"id": "master-key-1",
"type": "AES"
}
其中 key 字段值替换为上一步生成的 64 位 hex 字符串,id 必须唯一且不能含空格或特殊字符。MySQL 启动后,可通过以下语句验证主密钥是否加载成功:
SELECT * FROM performance_schema.keyring_keys WHERE KEY_ID = 'master-key-1';
若无结果,说明插件未生效或 JSON 格式错误(常见于多出逗号、引号不匹配)。
创建加密表的实际操作与陷阱
插件就绪且主密钥验证通过后,才能创建加密表。语法本身简单,但有三个关键约束:
- 仅支持
innodb_file_per_table=ON的独立表空间(共享表空间ibdata1不支持加密) - 必须显式指定
ENCRYPTION='Y',即使default_table_encryption=ON已设,新建表也不会自动继承(这是 8.0.16 之前的 Bug,8.0.16+ 才修复) - 加密表无法修改为非加密(
ALTER TABLE ... ENCRYPTION='N'报错),只能导出再重建
示例建表语句:
CREATE TABLE t1 ( id INT PRIMARY KEY, data VARCHAR(100) ) ENCRYPTION='Y' ENGINE=InnoDB;
建表后检查是否生效:
SELECT NAME, ENCRYPTION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME LIKE '%t1%';
返回 ENCRYPTION 值为 Y 才表示成功。注意:加密只作用于数据页(.ibd 文件),表结构(FRM)、日志(binlog/redo)、临时表均不加密。
备份与恢复加密表的硬性前提
mysqldump 无法导出加密表的真实数据——它读取的是解密后的结果,备份文件本身不加密。若需物理备份(如 xtrabackup),必须确保备份时 keyring_file 插件已加载且密钥文件完整可用。最易被忽略的一点:备份出来的 .ibd 文件脱离原密钥环境后完全不可用,哪怕在同一台机器上,只要 MySQL 重启过且密钥文件被覆盖,就再也打不开。
因此,密钥文件必须和数据库备份一起归档,且严禁用 cp 或 rsync 单独同步 .ibd 文件。如果做主从,从库必须配置完全相同的 keyring_file_data 路径和内容,否则复制线程遇到加密表会中断并报错:Encrypted tablespace cannot be accessed without keyring plugin。











