默认情况下,MySQL 复制(包括组复制)在将已由其他服务器接受的事务应用到副本或组成员时不执行权限检查。您可以创建一个具有适当权限的用户帐户来应用通常在通道上复制的事务,并将其指定为复制应用器的 PRIVILEGE_CHECKS_USER
帐户,使用 CHANGE REPLICATION SOURCE TO
语句。然后,MySQL 会针对用户帐户的权限检查每个事务,以验证您是否已授权该通道进行该操作。该帐户也可以安全地由管理员用于应用或重新应用来自 mysqlbinlog 输出的事务,例如从通道上的复制错误中恢复。
使用 PRIVILEGE_CHECKS_USER
帐户有助于保护复制通道免受对特权或不需要的操作的未授权或意外使用。在以下情况下,PRIVILEGE_CHECKS_USER
帐户提供了额外的安全层
您正在组织网络上的服务器实例与另一个网络上的服务器实例之间进行复制,例如由云服务提供商提供的实例。
您希望将多个内部部署或异地部署作为单独的单元进行管理,而不授予一个管理员帐户对所有部署的权限。
您希望拥有一个管理员帐户,该帐户允许管理员仅执行与复制通道及其复制的数据库直接相关的操作,而不是在服务器实例上拥有广泛的权限。
您可以通过在 CHANGE REPLICATION SOURCE TO
语句中指定通道的 PRIVILEGE_CHECKS_USER
帐户时,将一个或两个选项添加到其中来提高应用权限检查的复制通道的安全
该
REQUIRE_ROW_FORMAT
选项使复制通道仅接受基于行的复制事件。当设置REQUIRE_ROW_FORMAT
时,您必须在源服务器上使用基于行的二进制日志记录 (binlog_format=ROW
)。使用基于语句的二进制日志记录,PRIVILEGE_CHECKS_USER
帐户可能需要一些管理员级权限才能成功执行事务。选项
REQUIRE_TABLE_PRIMARY_KEY_CHECK
使得复制通道使用其自身的策略来进行主键检查。设置ON
表示始终需要主键,设置OFF
表示从不需要主键。默认设置STREAM
使用从源复制的每个事务的值设置系统变量sql_require_primary_key
的会话值。当设置了PRIVILEGE_CHECKS_USER
时,将REQUIRE_TABLE_PRIMARY_KEY_CHECK
设置为ON
或OFF
表示用户帐户不需要会话管理级别权限来设置受限制的会话变量,而这些变量是更改sql_require_primary_key
值所必需的。它还规范了不同源的复制通道的行为。
授予 REPLICATION_APPLIER
权限,使用户帐户能够在复制应用线程中充当 PRIVILEGE_CHECKS_USER
,并执行由 mysqlbinlog
使用的内部使用 BINLOG
语句。用于 PRIVILEGE_CHECKS_USER
帐户的用户名和主机名必须遵循 第 8.2.4 节,“指定帐户名” 中描述的语法,并且用户不能是匿名用户(具有空白用户名)或 CURRENT_USER
。若要创建新帐户,请使用 CREATE USER
。若要授予此帐户 REPLICATION_APPLIER
权限,请使用 GRANT
语句。例如,若要创建用户帐户 priv_repl
,管理员可以从 example.com
域中的任何主机手动使用此帐户,并且需要加密连接,请发出以下语句
mysql> SET sql_log_bin = 0;
mysql> CREATE USER 'priv_repl'@'%.example.com' IDENTIFIED BY 'password' REQUIRE SSL;
mysql> GRANT REPLICATION_APPLIER ON *.* TO 'priv_repl'@'%.example.com';
mysql> SET sql_log_bin = 1;
语句 SET sql_log_bin
用于使帐户管理语句不会添加到二进制日志中并发送到复制通道(请参阅 第 15.4.1.3 节,“SET sql_log_bin 语句”)。
身份验证插件 caching_sha2_password
是新用户的默认插件(有关详细信息,请参阅 第 8.4.1.1 节,“缓存 SHA-2 可插拔身份验证”)。若要使用使用此插件进行身份验证的用户帐户连接到服务器,您必须按照 第 19.3.1 节,“设置复制以使用加密连接” 中的说明设置加密连接,或者启用未加密连接以支持使用 RSA 密钥对进行密码交换。
设置用户帐户后,请使用 GRANT
语句授予其他权限,以使用户帐户能够执行您希望应用线程执行的数据库更改,例如更新服务器上持有的特定表。这些相同的权限使管理员能够在需要手动在复制通道上执行任何这些事务时使用该帐户。如果尝试执行您没有授予相应权限的意外操作,则该操作将被禁止,并且复制应用线程将停止并出现错误。 第 19.3.3.1 节,“用于复制 PRIVILEGE_CHECKS_USER 帐户的权限” 解释了帐户需要哪些其他权限。例如,若要授予 priv_repl
用户帐户 INSERT
权限,以将行添加到 db1
中的 cust
表,请发出以下语句
mysql> GRANT INSERT ON db1.cust TO 'priv_repl'@'%.example.com';
您可以使用 CHANGE REPLICATION SOURCE TO
语句为复制通道分配 PRIVILEGE_CHECKS_USER
帐户。如果复制正在运行,请在 CHANGE REPLICATION SOURCE TO
语句之前发出 STOP REPLICA
,并在之后发出 START REPLICA
。强烈建议在设置 PRIVILEGE_CHECKS_USER
时使用基于行的二进制日志记录;您可以使用该语句将 REQUIRE_ROW_FORMAT
设置为强制执行此操作。
重新启动复制通道后,从该时间点开始应用对动态权限的检查。但是,静态全局权限在应用程序上下文中不会生效,直到您重新加载授权表,因为这些权限不会针对已连接的客户端进行更改。若要激活静态权限,请执行刷新权限操作。这可以通过发出 FLUSH PRIVILEGES
语句或执行 mysqladmin flush-privileges 或 mysqladmin reload 命令来完成。
例如,若要在正在运行的副本上启动通道 channel_1
上的权限检查,请发出以下语句
mysql> STOP REPLICA FOR CHANNEL 'channel_1';
mysql> CHANGE REPLICATION SOURCE TO
> PRIVILEGE_CHECKS_USER = 'priv_repl'@'%.example.com',
> REQUIRE_ROW_FORMAT = 1 FOR CHANNEL 'channel_1';
mysql> FLUSH PRIVILEGES;
mysql> START REPLICA FOR CHANNEL 'channel_1';
如果您未指定通道且不存在其他通道,则该语句将应用于默认通道。通道的 PRIVILEGE_CHECKS_USER
帐户的用户名和主机名显示在 Performance Schema replication_applier_configuration
表中,它们经过适当的转义,以便可以直接复制到 SQL 语句中以执行单个事务。
如果您使用的是 Rewriter
插件,则应授予 PRIVILEGE_CHECKS_USER
用户帐户 SKIP_QUERY_REWRITE
权限。这将阻止此用户发出的语句被重写。有关更多信息,请参阅 第 7.6.4 节,“Rewriter 查询重写插件”。
当为复制通道设置了 REQUIRE_ROW_FORMAT
时,复制应用程序不会创建或删除临时表,因此不会设置会话系统变量 pseudo_thread_id
。它不会执行 LOAD DATA INFILE
指令,因此不会尝试进行文件操作以访问或删除与数据加载相关的临时文件(记录为 Format_description_log_event
)。它不会执行 INTVAR
、RAND
和 USER_VAR
事件,这些事件用于为基于语句的复制复制客户端的连接状态。(例外情况是与 DDL 查询关联的 USER_VAR
事件,这些事件将被执行。)它不会执行在 DML 事务中记录的任何语句。如果复制应用程序在尝试排队或应用事务时检测到任何这些类型的事件,则不会应用该事件,并且复制将停止并出现错误。
您可以为复制通道设置 REQUIRE_ROW_FORMAT
,无论您是否设置了 PRIVILEGE_CHECKS_USER
帐户。当您设置此选项时实现的限制提高了复制通道的安全性,即使没有权限检查也是如此。您还可以在使用 mysqlbinlog 时指定 --require-row-format
选项,以在 mysqlbinlog 输出中强制执行基于行的复制事件。
安全上下文。 默认情况下,当使用指定为 PRIVILEGE_CHECKS_USER
的用户帐户启动复制应用线程时,安全上下文将使用默认角色创建,或者如果 activate_all_roles_on_login
设置为 ON
,则使用所有角色创建。
您可以使用角色为用作 PRIVILEGE_CHECKS_USER
帐户的帐户提供通用权限集,如下面的示例所示。在此,而不是像前面的示例中那样直接授予 db1.cust
表的 INSERT
权限,而是将此权限授予角色 priv_repl_role
以及 REPLICATION_APPLIER
权限。然后,使用该角色将权限集授予两个用户帐户,这两个帐户现在都可以用作 PRIVILEGE_CHECKS_USER
帐户
mysql> SET sql_log_bin = 0;
mysql> CREATE USER 'priv_repa'@'%.example.com'
IDENTIFIED BY 'password'
REQUIRE SSL;
mysql> CREATE USER 'priv_repb'@'%.example.com'
IDENTIFIED BY 'password'
REQUIRE SSL;
mysql> CREATE ROLE 'priv_repl_role';
mysql> GRANT REPLICATION_APPLIER TO 'priv_repl_role';
mysql> GRANT INSERT ON db1.cust TO 'priv_repl_role';
mysql> GRANT 'priv_repl_role' TO
'priv_repa'@'%.example.com',
'priv_repb'@'%.example.com';
mysql> SET DEFAULT ROLE 'priv_repl_role' TO
'priv_repa'@'%.example.com',
'priv_repb'@'%.example.com';
mysql> SET sql_log_bin = 1;
请注意,当复制应用线程创建安全上下文时,它会检查 PRIVILEGE_CHECKS_USER
帐户的权限,但不会执行密码验证,也不会执行与帐户管理相关的检查,例如检查帐户是否被锁定。创建的安全上下文在复制应用线程的整个生命周期内保持不变。