注意
AWS の人に Aurora について色々質問する機会があり、コネクションプールを実装するために failover への追従について話を聞けました。
まだ自分で実装して検証したわけではないので間違っている部分があるかもしれません。
背景
通常、Aurora MySQL の Cluster endpoint に接続すると、書き込み可能なサーバーに接続することができます。
しかし、 failover が発生するとこのサーバーが replica に降格することがあります。長時間接続を維持するコネクションプールを使っている場合、ちゃんと書き込み可能なサーバーにつなぎ直さなければなりません。
innodb_read_only
接続先が Read replica だった場合、 innodb_read_only
という変数が On になっています。 クエリを投げる前、あるいはトランザクションを開始する前に select @innodb_read_only
というクエリで 1 が返ってきたら再接続するというのが素朴な実装です。
更新クエリを投げたときに "The MySQL server is running with the --read-only option ..." というエラーになるので、それが発生したら再接続するという手もあります。
しかし、autocommit なら簡単に(アプリに手を加えなくてもコネクションプール側で)クエリの再実行ができますが、トランザクションを使ってる場合はリトライが面倒なので、その場合は select @innodb_read_only
の方がいいでしょう。
mysql.ro_replica_status
failover が発生して再接続する時、 cluster endpoint に再接続すると、DNSの反映が遅くてまた古い writer に接続してしまうことがあります。
もっと早く failover に追従するために、古い接続を切る前に SELECT SERVER_ID FROM mysql.ro_replica_status WHERE SESSION_ID = 'MASTER_SESSION_ID'
することができます。
このテーブルはDNSよりも failover への追従が早いので、 Aurora Cluster の member のリストを持っておけば、この SERVER_ID から member を選択して接続することができるはずです。 (ro_replica_status からIPアドレスかホスト名が取れればいいのに...)
この方法を使った高速な failover 対応がすでに MariaDB Connector/J の ODBC ドライバで実装されているようなので、自分で実装するときに参考にすることができるはずです。
追記
ちょうどローカルのDNSを使って高速 failover 対応をする方法を DeNA さんが公開してくださっていたのでリンクしておきます。