在站点冗余的 galera 集群上,只有在法定数量的数据库节点接受了事务后,才能返回提交。如果一个数据库节点宕机,所有的提交将被集群的其余部分保留,并且宕机的数据库节点将在再次启动数据库时与集群的其余部分同步。如果数据库应该已经损坏,可以随时核对 mysql 数据目录并从一个空数据库开始,它最终会赶上集群的其余部分。因此,听起来我们可以通过关闭确保本地 ACID 合规性的选项来调整性能。
所以这里的问题真的是......“可能会出什么问题?”
:-)
根据评论,我将提供有关我们特定设置的一些信息:
集群由三个节点组成。其中两个在生产中被积极使用,其中一个比另一个使用得更频繁。第三个节点仅用于仲裁和备份目的。
站点冗余意味着节点位于不同的服务器中心。我发现很难想到会导致两个节点同时关闭的任何事情——除了一个严重的 mysql 错误,这有多大可能?诚然,其中两个节点相距不到 10 公里(备份/仲裁节点相隔数百公里,外加国界)。一枚中型核弹可能会同时摧毁两个节点……再说一次,在这种情况下,“我们的数据库有问题”可能是我们最不关心的问题。太阳风暴可能同时摧毁两个或所有服务器吗?
我们的性能问题是主要的,因为我们的 SAN 上的写入缓存有时会满。我们正在努力缓解这个问题,但我们不能保证它不会再次发生。我们时不时地会遇到“打嗝”,我们的交易等待大约 10-30 秒。
在这个特定的设置中,30 秒的延迟实际上可能是生死攸关的问题。好吧,很可能不是,但如果客户这样认为,那就够糟糕了。如果整个集群出现故障,合理的低延迟和快速恢复是最紧迫的优先事项。丢失一些交易可能已经够糟糕了,但这不是生死攸关的问题。
我们看到的性能问题是写入事务卡在“wsrep in pre-commit”状态。这不是流量控制问题,只是一个节点有问题。我对它进行了一些研究,显然是所有本地写入查询都在等待锁定,而节点正在将远程变更集写入数据库。这个问题应该在 galera 4 中修复,但升级目前不是一个选项。
我们的性能问题只在一个节点上,所以它只在一个节点上我正在考虑关闭那些东西。我会在我们的文档中添加无论发生什么,所说的节点都不应该用于引导集群。
我们不做分片,也不打算做任何分片。除了那些打嗝,我们没有任何性能问题。
我现在已经对此进行了一些研究,所以我将回答我自己的问题。
先总结
如果仅在一个节点上观察到性能问题,关闭受影响节点上的 innodb_doublewrite 和 innodb_flush_log_at_trx_commit是完全安全的——只要记住在整个集群出现故障时使用其他节点之一进行引导。
此外,在真正的站点冗余 galera 集群中,在任意数量的节点上将 innodb_flush_log_at_trx_commit 设置为 2 并将 sync_binlog 设置为 0应该是相当安全的。如果遇到性能问题,如果正常运行时间和性能很重要,并且如果丢失的交易可能不是生死攸关的问题 - 那么无需犹豫,继续做吧。
如果性能比 ACID 合规性更重要,人们也可以继续关闭双重写入。发生灾难的可能性非常低。
我可以看到坚持“安全”设置的两个原因:
节点健壮性:保持 innodb_doublewrite 开启
innodb_doublewrite 可以在一个节点上安全地关闭而不会失去对 ACID 的兼容性,但打开它可能仍然更好。根据何时禁用 InnoDB 双写缓冲是安全的?关闭 innodb-doublewrite 可能会导致数据损坏,在这种情况下,可能需要擦除已关闭节点上的数据分区并重新启动它。这带来了三个成本:
(据我所知,日志文件丢失刷新不应该导致启动数据库节点的问题 - 即对于 innodb_flush_log_at_trx_commit 手册明确指出“InnoDB 的崩溃恢复工作不管值”)
整个集群可能一次烧毁的原因
硬爆炸
考虑将 innodb_flush_log_at_trx_commit 设置为 2,将 binlog_sync 设置为 0,将 innodb-doublewrite-buffering 设置为 1,这可能会提高性能,据我所知,它不会涵盖的唯一故障模式是仲裁的节点正在遭受断电或内核恐慌。对于真正的多站点设置,这些似乎非常罕见,以至于人们可能想要忽略它们。
如果节点位于附近,则本地问题,即停电、洪水、火灾等可能会同时将所有节点击倒。我多次目睹整个服务器站点由于最奇怪的原因而崩溃,即使一切都应该是多余的。
太阳风暴会同时影响整个星团吗?特别是如果集群位于同一个城市和极地地区?我已经看到两台笔记本电脑同时崩溃,在太阳风暴期间位于极地地区,并且没有其他合理的原因(不同的操作系统,它不是闰秒等)。
如果所有节点都运行相同的操作系统,则某些操作系统内核问题可能会导致所有节点在完全相同的时间因内核崩溃而严重崩溃。
软件崩溃
我相信如果 innodb_flush_log_at_trx_commit 设置为 0 或 innodb_flush_log_at_trx_commit 设置为 0,那么同时影响所有节点的 mysql 崩溃可能会导致数据丢失。
有没有人观察到 galera 以这种方式崩溃?
系统管理员或错误脚本也在所有节点上同时在 mysql 上执行“kill -9”......但是如果系统管理员想要导致数据丢失,他可能会找到一种方法,而不管这些设置如何。
集群因其他原因而关闭
在这些情况下,这些设置无关紧要:
所有三个节点之间突然和完全的网络隔离,或者使集群碎片化,因此无法找到仲裁。发生此类事件后需要引导集群,如果真的想 100% 确定没有事务丢失,则需要手动调查二进制日志(请参阅下面的更多内容) - 但由于 mysql 和操作系统都没有崩溃,无论同步设置如何,最终都会同步所有状态。
糟糕的时机 - 即一个节点宕机,而当它宕机时,另一个节点可能宕机,或者可能存在一些网络隔离。之后,需要引导集群。但是,节点收到的所有内容都将写入磁盘,因此上述设置不会影响任何内容。(我们曾经遇到过这种情况)。
集群故障需要人工干预
无论设置如何,为了 100% 确保在灾难性集群故障后不会丢失任何事务,实际上需要手动检查/合并 binlog。我们只需要使用一个节点来引导集群,但我们不知道这个节点是否获得了所有的变更集,这个信息只能通过调查所有节点的 binlogs 获得(
log_slave_updates
打开后,可能可以使用来自一个节点的 binlogs节点的法定人数)。这意味着您需要提前做出决定——如果我们遇到灾难性的集群崩溃,应该优先考虑什么?是让集群尽快启动并再次运行的优先级,还是在引导集群之前确保 100% 没有事务丢失?
你的旅费可能会改变
如果在极端情况下某些停机时间是可以接受的(完全灾难性的数据库集群崩溃是极端的),并且如果在返回生产模式之前确保所有事务都到位至关重要,那么需要 100% 确保二进制日志已同步并保留,并且备份机制很好。同步 innodb 日志和双重写入是非关键的,如果这能带来性能优势,可以将其关闭。
如果“让集群尽快启动并再次运行”很重要,那么
set innodb_flush_log_at_trx_commit = 1
对set innodb_doublewrite = 1
节点的法定人数也很重要;如果集群应该关闭,那么它可以从任何打开了这些设置的服务器快速引导。(可能需要考虑一下。在我们之前的崩溃中,节点 C 跌倒并再次站起来。在节点 C 正确加入集群之前,节点 A 和节点 B 之间的网络故障,导致关闭。显然,我们可以从 A 引导或 B 没有任何数据丢失,但不是来自 C)。“站点冗余”是指您在 3 个不同的数据中心中的每一个中都有 1 个节点吗?
您的目标是在任何单点故障中幸存下来吗?包括任何一台服务器甚至一个数据中心的硬崩溃?
如果发生硬崩溃,你愿意强制 SST 吗?
然后我“相信”这 3 个设置可以设置为快速但不安全的设置。
(根据我的建议退款保证。)