web-dev-qa-db-ja.com

Galeraクラスターへの大量の書き込み-テーブルがロックされ、クラスターは実質的に使用できません

3つのノードにGaleraClusterをセットアップしました。データの読み取りに最適です。クラスターでテストを行うための簡単なアプリケーションを実行しました。残念ながら、私が何かを書き込もうとすると、クラスターは完全に失敗すると言わざるを得ません。たぶんそれは異なって設定することができますか、それとも私は間違っていますか?

簡単なストアドプロシージャがあります。

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クライアントを別々のスレッドで作成し、列 'counter' = 0のレコードがなくなるまで、各クライアントが100ミリ秒ごとにプロシージャを実行します。

残念ながら、約10秒後にsthが悪化​​します。サーバーには、決して終了しないプロセス 'query_end'があります。その後、テストテーブルを更新することはできません。MySQLは次を返します。

エラー1205(HY000):ロック待機タイムアウトを超えました。トランザクションを再開してみてください

。 mysqlを再起動することさえできません。あなたができることは、サーバー、時にはクラスター全体を再起動することです。大規模な同時書き込み/更新を行う場合、Galera Clusterはそれほど信頼性がありませんか?信じがたい。

2
Joe

ほぼ同じ問題が発生しました。更新時に、ロックタイムアウトで失敗しました。現在の戦略は、バックグラウンドプロセスと大量の書き込みに1台のサーバーを使用し、ライブWebサーバーに他の2台のサーバーを使用することです。

HAProxyを使用している場合、これは非常に簡単ですが、コードにもいくつか変更を加える必要がありました。

これまでのところ、はるかにうまく機能しているように見えますが、数週間以内にうまく機能するかどうかを確実に確認します(同じ問題が発生しない場合)。

私たちの経験からのいくつかのメモ:

数週間後、私は変更が本当に大きな違いを生んだと言うことができます。最も重要な変更は、バックグラウンドプロセスを分析してスケジュールすることでした。これにより、プロセスが重複しないようになります(または重複しなくなります)。

サーバーを変更すると、主に1台のサーバーが書き込みに使用され、他の2台のサーバーが読み取りに使用されるため、バックグラウンドプロセスが多い場合のユーザーエクスペリエンスが向上します。

私たちが行った3番目のステップは、バックグラウンドプロセスを改善することでした。 1つのトランザクション中に、プログラマーはテーブルを削除し、ゼロから再構築しました。これを変更して、最初に変更が必要かどうかを確認してから、行を更新しました。これにより、このプロセスのパフォーマンスが大幅に向上しました。

私たちの経験では、Galeraクラスターでは読み取りは非常に高速ですが、特に大量の書き込み操作を実行している場合は、書き込みがかなり遅くなる可能性があります。最初はいくつかの問題があり、テーブル全体を再インポートする必要がありました。これはデータベースにとって大きなキラーでした。サーバーを2回クラッシュさせたもう一つのことは、binlogがサーバーのディスクをいっぱいにし、サーバーをクラッシュさせたことです。また、必ずすべてのデータベースをInnodbテーブルに変更してください。そうしないと、データが失われる可能性があります。プログラマーの1人がすべてのログテーブルをMyISAMに設定しました。たとえば、このプロセスでログの一部が失われたとします。

しかし、結局のところ、ガレラは現在かなりうまく機能していると言えます。 DBサーバーを更新したり、その他のメンテナンスを行ったりする必要がある場合は特に便利です。メンテナンスを行うために1つのノードをシャットダウンする場合は大きな問題ではないからです。

2
bernhardrusch

遅いことはわかっていますが、ここでガレラクラスターに関する私の経験を少し残しておきます。私たちのアプリケーションは約160-200の挿入/秒を実行しており、同じくらい多くの読み取りを実行します。夜はそれよりはるかに少ないですが、日中はこれが私たちの平均であり、雇用率にピークを迎えることがあります。私たちはおそらくあなたのアプリケーションと同じコンテキストではありませんが、標準のMySQLからGaleraに移行したときに私たちを助けたのは、各トランザクションを自動コミットするようにアプリケーションを設定し、この質問で説明している動作を即座に削除したことです。

python PySQLPoolライブラリを使用して、クエリラッパーに次のような行を追加する必要がありました。

PySQLPool.getNewQuery(self.connection, commitOnEnd=True)

次に、私たちが直面したもう1つの問題は、テーブルへの書き込み速度が十分でないことでした。十分に高速にするために私たちが見つけた1つの方法は、innodb_flush_log_at_trx_commitオプションを使用することでした。トランザクションが1秒間失われる余裕があるため、my.cnfで次のように設定しました。

innodb_flush_log_at_trx_commit  = 0

これらの2つの簡単な設定により、Galeraを使用して1年以上本番環境に移行し、3台のサーバーがアプリケーションで適切に機能しています。

ベスト。

0
drivard