可以mysqldump --single-transaction
在不停止复制的情况下在从属数据库上运行吗(stop slave;
)?这是用于定期每日备份,以便在发生存储灾难时我们可以恢复主数据库。大多数表都是 InnoDB,只有几个是 MyISAM。
官方文件称:
“您应该在开始转储过程之前停止从属服务器上的复制,以确保转储包含一组一致的数据”。
这是什么意思consistent data
?这是否意味着像最新数据?
我知道--single-transaction
这意味着它从发布时开始就获取数据,因此在转储发生时新的进一步更改将不是记录到转储中。我说得对吗?
我们不想在主服务器上运行备份,因为它会给我们的应用程序带来滞后。
答案1
stop slave
TL;DR -在副本上使用备份时,您实际上不需要发出。如果您mysqldump
使用默认值运行并省略--single-transaction
,则默认情况下将使用锁定备份,这将自动阻止备份期间对数据库的任何更改;保持数据的一致性。这通常意味着延迟复制,但它会在备份完成时自行恢复。
MySQL 是一个关系数据库,这意味着一个表中的数据可能与另一个表中的数据有关系。例如,如果您正在接受在线订单,则可能有一个line_items
表,其中一行或多行属于该orders
表的一条记录,而该表又可能有一行或多行属于该users
表的一条记录。
MyISAM 是一种非事务性存储引擎,这意味着无论选择哪种方式,其数据都将被允许在备份期间更改--single-transaction
。以前面的示例为例,我们假设它line_items
是 MyISAM。您启动备份,并且您的一位用户在备份运行时提交了订单。
update users set last_ordered_at=now() where id=306; insert into orders (user_id, created_at, ...) values (306, now(), ...); insert into line_items (order_id, product_id, ...) values (1021992, 10509, ...);
如果备份在运行之前没有读取line_items
表并且您执行恢复,则结果为:
- 订单表的最大 ID 重置为低于
1021992
line_items 记录的值,因此暂时处于孤立状态。 - 更改
last_ordered_at
已丢失 - 当添加其他订单时,order_id 到达
1021992
该订单时会神奇地添加此 line_item 记录(除非该级别有其他过滤器)。line_items
在备份到达该表之前添加的任何内容都会出现此问题。 - 猫和狗生活在一起……集体歇斯底里。
如果您的 MyISAM 数据是静态/不变的,那么使用--single-transaction
就不会有问题,并且您的数据将保持一致。但请记住,现在数据是静态的,并不意味着它会一直保持静态。
如果您的 MyISAM 数据仅与其他 MyISAM 数据相关,而与事务数据无关,则可以将 MyISAM 数据移动到单独的模式,以便在备份期间可以将其与事务数据区别对待。
从 MySQL 5.6 开始,InnoDB 支持全文索引,因此 MyISAM 表实际上已经没什么用了。您可以考虑使用类似 的语句将它们转换为 InnoDB alter table [tablename] engine=innodb;
。与任何更改一样,您应该在继续生产之前在开发/UAT 中对此进行评估。要一次创建所有 alter 语句,您可以使用:
select concat('alter table ', table_schema, '.', table_name, ' engine=innodb;') from information_schema.tables where engine='MyISAM' and table_schema not in ('mysql','information_schema','performance_schema');
InnoDB 使用的物理空间大约是 MyISAM 的 2-3 倍,并且这些表在修改时将被锁定以防止写入;您需要相应地规划转换。完成后,您可能需要检查服务器配置并将其调整为更适合 InnoDB。
使用 100% 事务表的一个注意事项--single-transaction
是,如果您在备份期间运行 DDL(CREATE、DROP、ALTER),这些不是事务语句,通常会导致备份运行失败。这通常是一种可以通过备份监控解决的极端情况。