我在 3 个节点上设置了 Galera 集群。它非常适合读取数据。我做了一些简单的应用程序来对集群进行一些测试。不幸的是,当我尝试进行一些写入时,集群完全失败了。也许可以进行不同的配置,或者我做错了什么?
我有一个简单的存储过程:
CREATE PROCEDURE testproc(IN p_idWorker INTEGER)
BEGIN
DECLARE t_id INT DEFAULT -1;
DECLARE t_counter INT ;
UPDATE test SET idWorker = p_idWorker WHERE counter = 0 AND idWorker IS NULL limit 1;
SELECT id FROM test WHERE idWorker = p_idWorker LIMIT 1 INTO t_id;
SELECT ABS(MAX(counter)/MIN(counter)) FROM TEST INTO t_counter;
SELECT COUNT(*) FROM test WHERE counter = 0 INTO t_counter;
IF t_id >= 0 THEN
UPDATE test SET counter = counter + 1 WHERE id = t_id;
UPDATE test SET idWorker = NULL WHERE id = t_id;
SELECT t_counter AS res;
ELSE
SELECT 'end' AS res;
END IF;
END $$
现在,我的简单 C# 应用程序在单独的线程中创建 3 个 MySQL 客户端,每个客户端每 100 毫秒执行一次该过程,直到没有列“counter”= 0 的记录。
不幸的是 - 大约 10 秒后,事情开始变得糟糕。服务器上有一个永不结束的进程“query_end”。之后 - 您无法对测试表进行更新,MySQL 返回:
错误 1205 (HY000):超过锁等待超时;尝试重新启动事务
。你甚至无法重启 mysql。你能做的就是重启服务器,有时是整个集群。当你进行大量并发写入/更新时,Galera Cluster 难道如此不可靠吗?难以置信。
答案1
我们遇到了几乎相同的问题 - 当我们更新时,它因锁定超时而失败。我们当前的策略是使用 1 个服务器进行后台进程和大量写入,并使用其他 2 个服务器作为实时 Web 服务器。
如果您使用 HAProxy,这非常简单 - 但我们也必须对代码进行一些更改。
到目前为止,它似乎运行得更好,但我们肯定会在几周后看看它是否运行良好(当我们不再遇到同样的问题时)。
根据我们的经验,我们得出以下几点结论:
几周后,我可以说这些变化确实带来了很大的不同。我认为最重要的变化是分析后台进程并对其进行调度,这样它们就不会重叠(或重叠程度不会太大)。
更改服务器,因此只有一台服务器主要用于写入,另外两台服务器用于读取,这在繁重的后台进程中改善了我们的用户体验。
我们采取的第三步是改进后台进程。在一次交易中,程序员删除了表并从头开始重建。我们将其改为先检查是否需要更改,然后更新行。这极大地提高了该进程的性能。
我们的经验是,在 Galera 集群中读取非常快,但写入可能非常慢,特别是当您执行大量写入操作时。我们一开始遇到了一些小问题,不得不重新导入整个表 - 这对数据库来说是一个很大的杀手。另一件导致我们的服务器两次崩溃的事情是 binlog 填满了服务器的磁盘,这导致服务器崩溃。还要确保将所有数据库更改为 Innodb 表,否则可能会丢失数据。我们的一名程序员将所有日志表设置为 MyISAM - 假设我们在此过程中丢失了一些日志。
但总而言之,我可以说 Galera 现在运行得很好。如果你需要更新数据库服务器或进行其他维护,它就特别好,因为如果你关闭一个节点进行维护,这不是什么大问题。
答案2
我知道已经很晚了,但我还是想在这里分享一下我在 Galera 集群上的经验。我们的应用程序每秒执行大约 160-200 次插入,并且执行同样多的读取。晚上要少得多,但白天这是我们的平均水平,并且可能会达到峰值。我们可能与您的应用程序不在同一环境中,但在我们从标准 MySQL 过渡到 Galera 时,帮助我们的是将我们的应用程序设置为自动提交每个事务,这立即消除了您在这个问题中描述的行为。
在 Python 中使用 PySQLPool 库时,我们必须在查询包装器中添加如下一行:
PySQLPool.getNewQuery(self.connection, commitOnEnd=True)
然后我们面临的另一个问题是它写入表格的速度不够快。我们发现一种让它足够快的方法是使用innodb_flush_log_at_trx_commit 选项。由于我们可以承受 1 秒的交易丢失,因此我们在 my.cnf 中进行了如下设置:
innodb_flush_log_at_trx_commit = 0
通过这两个简单的设置,我们现在使用 Galera 进行了一年多的生产,并且 3 台服务器在我们的应用程序上运行良好。
最好的。