RDS 不允许即使是主用户也没有超级权限,而这种权限是执行"FLUSH TABLES WITH READ LOCK"所必需的。(这是 RDS 的一个不幸限制)
"--master-data"选项生成了失败的语句,如果你想知道备份开始时的精确 binlog 坐标,这个选项当然是必须的。"FLUSH TABLES WITH READ LOCK"会对所有表获取全局只读锁,这允许mysqldump使用"START TRANSACTION WITH CONSISTENT SNAPSHOT" (就像使用"--single-transaction"一样) 然后使用 "SHOW MASTER STATUS" 来获取二进制日志坐标, 然后释放全局锁,因为它有一个事务将保持可见数据与该日志位置的状态一致。
RDS通过拒绝超级权限并提供没有明显解决方法来破坏了这个机制。
有一些hacky选项可用于正确解决此问题,但它们可能都不是特别吸引人:
在低流量期间进行备份。如果在开始备份之前和备份开始写入输出文件或目标服务器(假设你使用了"--single-transaction")之后的时间内binlog坐标没有更改,则此方法可行,因为你知道在进程运行时坐标不会改变。
在备份之前观察主服务器上的binlog位置,并使用这些坐标进行"CHANGE MASTER TO"。如果你的主服务器的"binlog_format"设置为"ROW",那么这应该可以工作,尽管你可能需要跳过一些初始错误,但不应该随后出现任何错误。这是行级复制非常确定性的结果,如果它试图插入已经存在的内容或删除已经消失的内容,它将停止。一旦通过了这些错误,您将得到一个真正的 binlog 坐标,即始终与一致快照开始时的坐标。
与上一项类似,但在恢复备份后,尝试使用mysqlbinlog --base64-output=decode-rows --verbose
读取主服务器的二进制日志来确定正确的位置,并检查新的从服务器以确定哪些事件必须在快照实际开始之前已经执行,然后使用这种方式确定的坐标来进行CHANGE MASTER TO
。
使用外部进程在服务器上获得对每个表的读锁,这将停止所有写入;观察来自SHOW MASTER STATUS
的二进制日志位置是否停止增加,然后开始备份,并释放那些锁。
如果你使用除最后一种方法之外的任何方法,特别是要进行表比较,以确保从服务器在运行时与主服务器完全相同,如果遇到后续的复制错误... 那就不是了。
可能是最安全的选项-但也可能是最烦人的 因为它似乎不应该是必要的-是先创建一个RDS读副本作为RDS主库。 一旦它与主服务器同步,您可以通过执行RDS提供的存储过程CALL mysql.rds_stop_replication
(在RDS 5.6.13和5.5.33中引入)停止RDS读副本上的复制,这不需要SUPER
权限。
将RDS读副本从服务器停止后,从RDS读副本获取您的mysqldump
,它现在具有特定一组主坐标的不变数据集。 将此备份还原到您的离线从服务器,然后使用RDS读副本的主坐标-SHOW SLAVE STATUS
Exec_Master_Log_Pos
和Relay_Master_Log_File
-作为您的CHANGE MASTER TO
坐标。
在从服务器上显示的 Exec_Master_Log_Pos
值是下一个要处理的事务或事件的起始点,这正是您的新从服务器需要在主服务器上开始阅读的地方。
然后,一旦您的外部从服务器正常运行,就可以停用 RDS 只读副本。
SELECT、INSERT、UPDATE、DELETE、CREATE、DROP、RELOAD、PROCESS、REFERENCES、INDEX、ALTER、SHOW DATABASES、CREATE TEMPORARY TABLES、LOCK TABLES、EXECUTE、REPLICATION SLAVE、REPLICATION CLIENT、CREATE VIEW、SHOW VIEW、CREATE ROUTINE、ALTER ROUTINE、CREATE USER、EVENT
,我缺少哪些权限?有什么想法吗? - JavaGuy