
前言
这篇文章聊聊 MySQL Keyring,下面统称为密钥环。
MySQL 服务器支持密钥环,使内部服务器组件和插件能够安全地存储敏感信息。用于数据的加密保护挺有用的。
什么是密钥环
我们先看看官网对此的描述:

大概意思为:
innodb 的加密架构由 主加密密钥和表空间加密密钥 组成,如果使用了表空间加密,表空间的密钥呗加密存在表空间的 header 中。需要访问表空间数据时,innodb就需要使用主加密密钥解密。加密的过程叫做静态数据加密。
表空间密钥的版本不会变,主加密密钥的版本可以变,改变的过程叫主密钥转换。
那么密钥环在其中是作为什么角色呢?
密钥环组件或插件做为主加密密钥的管理者存在的。
密钥环组件/插件作用
从 MySQL 5.7.11 开始,支持 keyring_file
(于 MySQL 8.0.34 版本开始被标记为弃用,可能在以后哪个版本删除),能够使用基于 keyring_file
文件的密钥环插件。
从 MySQL 8.0.24 开始,支持 component_keyring_file
,能够使用基于 component_keyring_file
文件的密钥环组件。
密钥环组件/插件有企业版和社区版,由于大多数小伙伴不使用企业版的 MySQL,所以这里不讲只在企业版存在的组件/插件。
密钥环组件有:
component_keyring_file
:将密钥环数据存储在服务器主机本地的文件中。
密钥环插件有:
keyring_file
:将密钥环数据存储在服务器主机本地的文件中。keyring_okv
:KMIP 1.1 插件,用于与 KMIP 兼容的后端密钥环存储产品。
前面说到密钥环组件/插件是管理者,那么密钥环服务可以管理哪些呢?
加密表空间的密钥 加密 binlog
密钥加密 redolog
密钥解密文件密钥的主密钥 解密持久化的敏感系统变量的值(8.0,必须启动密钥环组件而不是插件)
等会我们试一下功能。
密钥环组件安装
我们先从安装开始玩叭!!!
要安装密钥环组件需要两步:
编写一个清单,告诉服务器要加载哪个密钥环组件。 为该密钥环组件编写一个配置文件。
编写清单
清单又分为全局清单和本地清单两种:
看看官网是怎么描述的:

大概概括一下:
服务器安装目录(basedir/bin
,这里是个坑,我开始建在 basedir
怎么装都装不上,看了源码才知道原来是在 bin
下面与mysqld
同一级)里面有一个全局清单文件(mysqld.my
),如果指示使用本地清单文件(mysqld.my
),则服务器尝试从数据目录(datadir
)读取其本地清单文件。
清单文件不存在并不是错误。在这种情况下,服务器不会尝试加载与该文件关联的组件。
本地清单文件允许为服务器的多个实例设置组件加载,服务器实例的加载指令是特定于给定数据目录实例的。所以不同的实例可以使用不同的密钥环组件。
看下我这套环境的 basedir
和 datadir
还有 plugin_dir
(等会配置文件那里用)
root@localhost [(none)] 20:54:05 > select @@basedir,@@datadir,@@plugin_dir;
+----------------------------+---------------------+---------------------------------------+
| @@basedir | @@datadir | @@plugin_dir |
+----------------------------+---------------------+---------------------------------------+
| /application/mysql_8_3306/ | /data/mysql_8_3306/ | /application/mysql_8_3306/lib/plugin/ |
+----------------------------+---------------------+---------------------------------------+
1 row in set (0.00 sec)
查找一下看看在不在
find /application/mysql_8_3306/ -name "mysqld.my"
find /data/mysql_8_3306 -name "mysqld.my"
可以看到啥也没查到,因为我还没建呢哈哈,这也就表示,默认是不会创建这个文件的。
下面看看清单文件是怎么配置的,准备安装叭。
清单文件采用有效的 JSON 格式。
清单文件允许这些配置项:
"read_local_manifest"
:指示服务器是否应从本地清单文件读取组件加载信息,可选值为true
或false
。只允许在全局清单文件中配置。如果存在,首先检查该配置项的值如果值为 false
,则服务器处理全局清单文件中的其他配置项并忽略本地清单文件。如果值为 true
,服务器将忽略全局清单文件中的其他配置项并尝试读取本地清单文件。"components"
:此项表示要加载哪个组件。项目值是一个字符串,指定有效的组件 URN。组件 URN 以file://
开头并指定库文件名称。
如果要仅使用全局清单文件,需要在 basedir/bin 创建一个 mysqld.my ,并授予 mysql 操作系统只读权限,文件内容如下所示:
{
"components": "file://component_keyring_file"
}
或者,要使用全局和本地清单文件对,全局文件如下所示:
{
"read_local_manifest": true
}
使用本地清单文件的话,要在 datadir
创建一个 mysqld.my
,并授予 mysql 操作系统只读权限本地文件如下所示:
{
"components": "file://component_keyring_file"
}
OK,让我们试一下。我就一个实例,配置一下全局的就可以,考虑大家可能有多实例,我演示一下多实例配置方式。
先配置一下全局清单文件,输入到 basedir
cat <<EOF > /application/mysql_8_3306/bin/mysqld.my
{
"read_local_manifest": true
}
EOF
好了这样就是只读权限
[root@localhost log]# ll /application/mysql_8_3306/bin/mysqld.my
-rw-r--r--. 1 root root 34 10月 31 23:03 /application/mysql_8_3306/bin/mysqld.my
配置本地清单文件,输入到 data_dir
cat <<EOF> /data/mysql_8_3306/mysqld.my
{
"components": "file://component_keyring_file"
}
EOF
同样也是配置为只读权限
[root@localhost log]# ll /data/mysql_8_3306/mysqld.my
-rw-r--r--. 1 root root 52 10月 31 23:04 /data/mysql_8_3306/mysqld.my
密钥环组件配置文件
看看官网是怎么描述密钥环组件配置文件的:

大概概括一下:
初始化时,component_keyring_file
读取全局配置文件或与本地配置文件配对的全局配置文件:
组件尝试从组件库文件安装目录(即 plugin_dir
)读取其全局配置文件(component_keyring_file.cnf
)。如果全局配置文件指示使用本地配置文件(component_keyring_file.cnf
),则组件尝试从数据目录读取其本地配置文件。
如果没有配置文件存在,将会出现错误。没有有效配置的情况下,component_keyring_file
无法初始化。
本地配置文件允许设置多个服务器实例使用 component_keyring_file
,使得每个服务器实例的组件配置特定于给定的数据目录实例。这使得相同的密钥环组件可以与每个实例的不同数据文件一起使用。
下面看看 component_keyring_file
配置文件是怎么配置的,准备安装叭。
清单文件采用有效的 JSON 格式。
配置文件允许这些配置项:
"read_local_config"
:指示组件是否应从本地配置文件读取配置信息,可选值为true
或false
。此项仅允许在全局配置文件配置。如果该项不存在,则组件仅使用全局配置文件。如果存在,首先检查该配置项的值:如果值为 false
,则组件处理全局配置文件中的其他配置项,并忽略本地配置文件。如果值为 true
,则组件将忽略全局配置文件中的其他配置项,并尝试读取本地配置文件。"path"
:项目值是一个字符串,指定用于存储密钥环数据的文件。该文件应使用绝对路径命名,而不是相对路径。此项在配置中为必填项。如果未指定,component_keyring_file
初始化将失败。"read_only"
:该项值指示密钥环数据文件是否为只读。该项目值为true
(只读)或false
(读/写)。此项在配置中为必填项。如果未指定,component_keyring_file
初始化将失败。
如果要仅使用全局配置文件,需要在 plugin_dir
创建一个 component_keyring_file.cnf
,示例以读写模式配置路径为 ``/log/keyring_file`(名称随意) 的密钥环文件:
{
"path": "/log/keyring_file",
"read_only": false
}
或者,要使用全局和本地配置文件对,全局文件如下所示:
{
"read_local_config": true
}
本地文件如下所示:
使用本地配置文件的话,在 datadir
创建一个 component_keyring_file.cnf
,示例以读写模式配置路径为 ``/log/keyring_file`(名称随意) 的密钥环文件:
{
"path": "/log/keyring_file",
"read_only": false
}
我演示一下多实例配置方式。
先配置一下全局配置文件,输入到 plugin_dir
cat <<EOF> /application/mysql_8_3306/lib/plugin/component_keyring_file.cnf
{
"read_local_config": true
}
EOF
[root@localhost log]# ll /application/mysql_8_3306/lib/plugin/component_keyring_file.cnf
-rw-r--r--. 1 root root 32 10月 31 23:05 /application/mysql_8_3306/lib/plugin/component_keyring_file.cnf
配置本地配置文件,输入到 data_dir
cat <<EOF> /data/mysql_8_3306/component_keyring_file.cnf
{
"path": "/log/component_keyring_file",
"read_only": false
}
EOF
[root@localhost log]# ll /data/mysql_8_3306/component_keyring_file.cnf
-rw-r--r--. 1 root root 66 10月 31 23:14 /data/mysql_8_3306/component_keyring_file.cnf
创建密钥环文件
touch /log/component_keyring_file
chown mysql.mysql /log/component_keyring_file
查看一下
[root@localhost log]# ll component_keyring_file
-rw-r--r--. 1 mysql mysql 0 10月 31 23:14 component_keyring_file
然后重启一下 mysql
systemctl restart mysqld
怎么判断是否安装成功呢?
errorlog
输出
024-10-31T23:16:17.158278+08:00 0 [Note] [MY-013713] [Server] Component component_keyring_file reported: 'Keyring component initialized successfully.'
看 performance_schema.keyring_component_status
信息:
root@localhost [(none)] 23:16:20 > SELECT * FROM performance_schema.keyring_component_status;
+---------------------+-----------------------------+
| STATUS_KEY | STATUS_VALUE |
+---------------------+-----------------------------+
| Component_name | component_keyring_file |
| Author | Oracle Corporation |
| License | GPL |
| Implementation_name | component_keyring_file |
| Version | 1.0 |
| Component_status | Active |
| Data_file | /log/component_keyring_file |
| Read_only | No |
+---------------------+-----------------------------+
8 rows in set (0.00 sec)
Component_status
值为 Active
表示组件已成功初始化。
如果无法加载组件,服务器启动失败。如果组件加载但由于配置问题无法初始化,则服务器启动,但Component_status
值为 Disabled
。
看看 errorlog
,改完配置后,使用 ALTER INSTANCE RELOAD KEYRING
重新加载配置。
有小伙伴肯定要说了为什么不用不查看 mysql.component
?
让我们看一下:
root@localhost [(none)] 13:47:26 > SELECT * FROM mysql.component;
Empty set (0.00 sec)
可以看到实际上这里啥也没有
因为我们不是使用 INSTALL COMPONENT
注册的,只有使用 INSTALL COMPONENT
注册的才会往 mysql.component
写入一条数据。
这就引出另一个问题,为什么不选择 INSTALL COMPONENT
语句加载密钥环组件?
让我们讲讲这个问题:
注意
应该仅使用清单文件加载密钥环组件,不应使用 INSTALL COMPONENT
语句加载密钥环组件。使用该语句加载的密钥环组件可能在服务器启动序列中可用得太晚,对于使用密钥环的某些组件(如InnoDB
)可能会出现问题,因为它们在 mysql.component
系统表中注册并在随后的服务器重新启动时自动加载。但 mysql.component
是一个 InnoDB
表,因此其中命名的任何组件只能在 InnoDB 初始化后的启动期间加载。
如果在组件尝试访问密钥环服务时没有可用的密钥环组件或插件,该服务将无法被该组件使用。结果,该组件可能无法初始化,或者可能以有限的功能初始化。例如,如果 InnoDB
在初始化时发现有加密表空间,则会尝试访问密钥环。如果密钥环不可用,则 InnoDB
只能访问未加密的表空间。
密钥环插件安装
密钥环插件就不需要写这么多配置文件了,只需要在 my.cnf
写入以下内容重启就好了
[mysqld]
early-plugin-load=keyring_file.so
keyring_encrypted_file_data=/log/keyring-encrypted
keyring_encrypted_file_password=password
可以跳过以下语句查看是否加载插件
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE 'keyring%';
+--------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+--------------+---------------+
| keyring_file | ACTIVE |
+--------------+---------------+
我个人建议只使用 early-plugin-load
加载 keyring_file.so
,当然除了 --early-plugin-load
方法外,插件还可以通过 --plugin-load
或 --plugin-load-add
选项或 INSTALL PLUGIN
语句进行加载。然而,使用这些方法加载的密钥环插件可能在服务器启动序列的某些组件(如InnoDB
)使用密钥环时过晚可用:
使用 --plugin-load` 或
--plugin-load-add加载插件发生在
InnoDB` 初始化之后。使用 INSTALL PLUGIN
安装的插件将在mysql.plugin
系统表中注册,并在随后的服务器重启时自动加载。然而,由于mysql.plugin
是一个InnoDB
表,在启动时只能在InnoDB
初始化后加载其中命名的插件。
如果 InnoDB
在初始化时发现有加密的表空间,它会尝试访问密钥环。如果密钥环不可用,则 InnoDB
只能访问未加密的表空间。
这里不过多介绍密钥环插件,推荐使用组件。
加密测试
InnoDB
支持 file-per-table
表空间、general
表空间、mysql system tablespace
、redo logs
和 undo logs
的静态数据加密 。
database/table
我们来测试一下这些加密。
CREATE database enc DEFAULT ENCRYPTION = 'Y';
看一下定义:
root@localhost [(none)] 13:51:18 > show create database enc;
+----------+-------------------------------------------------------------------------------------------------------------------------------+
| Database | Create Database |
+----------+-------------------------------------------------------------------------------------------------------------------------------+
| enc | CREATE DATABASE `enc` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='Y' */ |
+----------+-------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
可以看到 DEFAULT ENCRYPTION='Y'
已经启动了
我们在其中创建一个表试试
root@localhost [(none)] 13:51:35 > use enc;
Database changed
root@localhost [enc] 13:52:59 > create table test(id int primary key,info text);
Query OK, 0 rows affected (0.10 sec)
root@localhost [enc] 13:53:11 > show create table test;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| test | CREATE TABLE `test` (
`id` int NOT NULL,
`info` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ENCRYPTION='Y' |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
可以看到表也是默认加密了。
这个适合就需要解释一个变量了:default_table_encryption
,8.0.16 开始可用,默认值为 OFF,所以平时创建 database
呢是默认不加密的。
它定义在创建 database
和通用表空间时未指定 ENCRYPTION
子句时应用于它们的默认加密设置。default_table_encryption
变量仅适用于用户创建的 database 和通用表空间。它不控制 mysql 系统表空间的加密。
还有一个:table_encryption_privilege_check
,8.0.16 开始可用,默认值为 OFF。
用于强制执行加密默认值 。当启用 table_encryption_privilege_check
后,在创建或更改具有与 default_table_encryption
设置不同的加密设置的 schema
或 general tablespaces
时 ,或者在创建或更改具有与默认 schema
加密不同的加密设置的表时,将发生权限(TABLE_ENCRYPTION_ADMIN
)检查。当 table_encryption_privilege_check
禁用时(默认),不会发生权限检查,并且允许前面提到的操作继续进行,但会发出警告。
让我们测试一下:
set global default_table_encryption=on;
set global table_encryption_privilege_check=on;
create user noenc identified by '123456';
grant create on enc.* to noenc;
创建一个不加密的表,可以看到是没法创建的:
noenc@localhost [enc] 14:06:01 > create table t(id int primary key)ENCRYPTION='N';
ERROR 3826 (HY000): Table encryption differ from its database default encryption, and user doesn't have enough privilege.
这时我们给它试试
grant SUPER on *.* to noenc;
可以看到 super
也不可以
noenc@localhost [enc] 14:08:05 > show grants;
+----------------------------------------+
| Grants for noenc@% |
+----------------------------------------+
| GRANT SUPER ON *.* TO `noenc`@`%` |
| GRANT CREATE ON `enc`.* TO `noenc`@`%` |
+----------------------------------------+
2 rows in set (0.01 sec)
noenc@localhost [enc] 14:08:04 > create table t(id int primary key)ENCRYPTION='N';
ERROR 3826 (HY000): Table encryption differ from its database default encryption, and user doesn't have enough privilege.
最后试试 TABLE_ENCRYPTION_ADMIN
revoke super on *.* from noenc;
grant TABLE_ENCRYPTION_ADMIN on *.* to noenc;
可以看到只有拥有 TABLE_ENCRYPTION_ADMIN
权限才能违背权限检查
noenc@localhost [(none)] 14:10:31 > show grants;
+----------------------------------------------------+
| Grants for noenc@% |
+----------------------------------------------------+
| GRANT USAGE ON *.* TO `noenc`@`%` |
| GRANT TABLE_ENCRYPTION_ADMIN ON *.* TO `noenc`@`%` |
| GRANT CREATE ON `enc`.* TO `noenc`@`%` |
+----------------------------------------------------+
3 rows in set (0.00 sec)
noenc@localhost [(none)] 14:10:35 > use enc
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
noenc@localhost [enc] 14:10:41 > create table t(id int primary key)ENCRYPTION='N';
Query OK, 0 rows affected (0.12 sec)
我们来测试一个特别的
set global default_table_encryption=off;
set global table_encryption_privilege_check=on;
revoke TABLE_ENCRYPTION_ADMIN on *.* from noenc;
table_encryption_privilege_check
的强制执行加密默认值,默认为不加密,那我创建加密表会不会检查?
让我们试一下
noenc@localhost [enc] 14:14:45 > select @@default_table_encryption,@@table_encryption_privilege_check;
+----------------------------+------------------------------------+
| @@default_table_encryption | @@table_encryption_privilege_check |
+----------------------------+------------------------------------+
| 0 | 1 |
+----------------------------+------------------------------------+
1 row in set (0.00 sec)
noenc@localhost [enc] 14:14:48 > show grants;
+----------------------------------------+
| Grants for noenc@% |
+----------------------------------------+
| GRANT USAGE ON *.* TO `noenc`@`%` |
| GRANT CREATE ON `enc`.* TO `noenc`@`%` |
+----------------------------------------+
2 rows in set (0.00 sec)
noenc@localhost [enc] 14:14:52 > create table t4(id int primary key)ENCRYPTION='Y';
Query OK, 0 rows affected (0.08 sec)
可以看到是不管的。
测试更改已有表的 database
的 ENCRYPTION
create database noenc ENCRYPTION='N';
create table t1(id int primary key);
insert into t1 select 1;
可以看到是未加密的
root@localhost [noenc] 16:00:52 > show create table t1;
+-------+----------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+----------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`id` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+----------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
我们更改一下 database
的加密并创建一个表
alter database noenc ENCRYPTION='Y';
create table t2(id int primary key);
可以看到后续是已加密的,反之相同。
root@localhost [noenc] 16:02:12 > show create table t2;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------+
| t2 | CREATE TABLE `t2` (
`id` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ENCRYPTION='Y' |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
general 表空间
下面我们测试一下general
表空间、mysql system tablespace
先看看 general
表空间,MySQL 8.0.13 引入了对 general tablespaces
的加密支持
从 MySQL 8.0.16 开始, 除非在 CREATE TABLESPACE
语句中显示指定 ENCRYPTION
子句,否则该 default_table_encryption
变量将确定新创建的 general tablespaces
的加密 。
在 MySQL 8.0.16 之前, 必须指定 ENCRYPTION
子句才能启用加密。
创建一个加密的 general
表空间
create tablespace g1 ENCRYPTION='Y';
创建一个表分配在里面
CREATE TABLE t3 (id INT PRIMARY KEY) TABLESPACE g1;
看一下表结构,可以看到即使没有显示指定也是默认加密。
root@localhost [noenc] 16:04:57 > show create table t3;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t3 | CREATE TABLE `t3` (
`id` int NOT NULL,
PRIMARY KEY (`id`)
) /*!50100 TABLESPACE `g1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci /*!80016 ENCRYPTION='Y' */ |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
这时候小伙伴就要问了,能不能把未加密的表移入 g1?
刚才 noenc.t1
是未加密的我们试一下:
root@localhost [noenc] 16:06:51 > alter table t1 TABLESPACE g1;
ERROR 3825 (HY000): Request to create 'unencrypted' table while using an 'encrypted' tablespace.
可以看到是不行的。
t2
是加密的是可以的
root@localhost [noenc] 16:07:34 > alter table t2 TABLESPACE g1;
Query OK, 0 rows affected (0.20 sec)
Records: 0 Duplicates: 0 Warnings: 0
独立表空间 datadir/noenc/t2.ibd
也没了
[root@localhost mysql_8_3306]# cd noenc/
[root@localhost noenc]# ll
总用量 112
-rw-r-----. 1 mysql mysql 114688 11月 1 16:00 t1.ibd
看看存在哪里了:
root@localhost [noenc] 16:20:42 > SELECT a.NAME AS space_name, b.NAME AS table_name ,c.PATH
-> FROM INFORMATION_SCHEMA.INNODB_TABLESPACES a
-> join INFORMATION_SCHEMA.INNODB_TABLES b on a.SPACE=b.SPACE
-> join INFORMATION_SCHEMA.INNODB_DATAFILES c on a.SPACE=c.SPACE
-> WHERE a.NAME LIKE 'g1';
+------------+------------+------------------------------------------+
| space_name | table_name | PATH |
+------------+------------+------------------------------------------+
| g1 | noenc/t2 | f1317c29-9827-11ef-a915-000c29945966.ibd |
| g1 | noenc/t3 | f1317c29-9827-11ef-a915-000c29945966.ibd |
+------------+------------+------------------------------------------+
2 rows in set (0.05 sec)
datadir/f1317c29-9827-11ef-a915-000c29945966.ibd
我们看一下
[root@localhost mysql_8_3306]# ll *.ibd
-rw-r-----. 1 mysql mysql 131072 11月 1 16:08 f1317c29-9827-11ef-a915-000c29945966.ibd
-rw-r-----. 1 mysql mysql 26214400 11月 1 16:08 mysql.ibd
OK查到了。没毛病。
mysql system tablespace
从 MySQL 8.0.16 开始,mysql system tablespace
支持加密。
mysql system tablespace
包含 mysql
系统数据库和 MySQL
数据字典表。默认情况下是未加密的。
ALTER TABLESPACE mysql ENCRYPTION = 'Y';
这样即可加密。
undo/redo 加密
使用 innodb_redo_log_encrypt
配置选项启用 redo logs
数据加密 。默认情况下, redo logs
加密是禁用的。
使用 innodb_undo_log_encrypt
配置选项启用 undo logs
数据加密。 undo logs
加密适用于驻留在 undo tablespaces
中的 undo logs
。
默认是不加密的。
root@localhost [noenc] 16:25:54 > show variables like '%log_encrypt';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| innodb_redo_log_encrypt | OFF |
| innodb_undo_log_encrypt | OFF |
+-------------------------+-------+
2 rows in set (0.01 sec)
这样即可加密:
set global innodb_redo_log_encrypt=1;
set global innodb_undo_log_encrypt=1;
Binary Log Files/Relay Log Files 加密
无需在服务器上启用二进制日志记录即可启用加密,因此您可以在没有二进制日志的副本上加密中继日志文件。
测试一下:
root@localhost [noenc] 16:38:14 > show binary logs;
+------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000130 | 197 | No |
+------------------+-----------+-----------+
1 rows in set (0.01 sec)
加密:
set global binlog_encryption=on;
可以查看,它立即切换了一个日志
root@localhost [noenc] 16:39:01 > show binary logs;
+------------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+------------------+-----------+-----------+
| mysql-bin.000130 | 244 | No |
| mysql-bin.000131 | 709 | Yes |
+------------------+-----------+-----------+
2 rows in set (0.01 sec)
插入一条试试
root@localhost [enc] 16:42:47 > insert into enc.t3 select 1;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
使用 mysqlbinlog 看一下能不能查看出来:
[root@localhost mysql_8_3306]# mysqlbinlog --base64-output=DECODE-ROWS -vv mysql-bin.000131
# The proper term is pseudo_replica_mode, but we use this compatibility alias
# to make the statement usable on server versions 8.0.24 and older.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
ERROR: Reading encrypted log files directly is not supported.
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
可以看到不支持查看了:
ERROR: Reading encrypted log files directly is not supported.
参考
https://dev.mysql.com/doc/refman/8.0/en/keyring-component-installation.html
https://dev.mysql.com/doc/refman/8.0/en/innodb-data-encryption.html
往期回顾
MySQL/PG 数据脱敏 - data_masking 插件和 postgresql_anonymizer 扩展初体验 MySQL/PG 对事务 DDL 的支持程度 - 从隐式提交聊到DDL事务 ONLINE DDL 收尾篇|如何有效实现 ONLINE - 关于 ONLINE DDL 的最佳实践 MySQL/PG 索引对于排序规则的依赖性 - 排序规则与索引的相关性问题,涉及到索引是否会失效 如何正确杀会话, KILL processlist_id/KILL QUERY? - 你知道如何正确杀掉活跃会话吗?
感谢阅读!关注我们获取更多精彩内容。




