LoginSignup
40
23

More than 5 years have passed since last update.

【注意】Amazon Aurora(MySQL)でZero Downtime Patch実行時に不具合が発生するケースがある【AWS】

Last updated at Posted at 2017-10-19

はじめに

先日、Amazon Aurora(MySQL)の必須アップデートの案内が来たのでアップデートの検証作業を実施しておりました。
Zero Downtime Patch(以下、ZDP)が実行され、ダウンタイム無しでアップデートが行われるはずが、不具合が発生してしまいました。

ググっても関連する情報が見つからなかったので、取り急ぎ分かっている情報について記録しておきます。

なお、対象のアップデートは下記のものになります。(Cluster Version 1.14)

Database Engine Updates 2017-08-07
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.20170807.html

ポイント(TL;DR)

重要なポイントは下記のとおりです。

  • Aurora(MySQL)に対し、DB Connection Poolを利用し、且つPrepared Statementを利用していると、Zero Downtime Patch実行時に不具合が発生する可能性が高い。
  • Aurora(MySQL)のアップデートを行う前に、アプリの構成・実装を調べた方が良い。

Zero Downtime Patch(ZDP)とは何か

Auroraを無停止(正確には5秒程度の遅延)でアップデートできる画期的な仕組みです。
アップデート処理中にも、クライアントからのDB接続は維持されます。

今回、Cluster Version 1.14へのアップデートとなりますが、本アップデートに関するドキュメントにも説明があります。
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.20170807.html

AuroraのCluster Version 1.10で初めて導入されたようです。
ZDPの内容について、下記ドキュメントにも記載があります。

Database Engine Updates 2016-12-14
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.20161214.html

こちらの記事も情報がまとまっていて参考になります。

Amazon Aurora のアップグレード
https://qiita.com/tonishy/items/542f7dd10cc43fd299ab

事象の内容

Aurora(MySQL)でClusterのアップデートが必要の旨の案内が来たため、AWS Management Consoleからアップデートを行いました。
AuroraのClusterアップデートは無事に完了しましたが、当該Auroraインスタンスを利用しているJavaアプリが軒並みエラーを吐き出し始めました。
その後Javaアプリを再起動し、復旧しました。

AWS Management Console上、WriterとなっているインスタンスのEventに下記のものが表示されました。
従って、Zero Downtime Patchが行われていたことは間違いありません。

The database was successfully patched with a zero downtime patch.

Javaアプリのログ上には、「Unknown prepared statement handler」といったエラーが多数出力されておりました。

事象の原因

当該JavaアプリはJDBC Connection Poolを利用し、DBとの接続を維持する構成になっています。
また、Prepared Statementを利用する実装になっております。

ZDP実行時、MySQLのクライアント(i.e. Javaアプリ)からの接続は維持されるようですが、Prepared Statementは維持されないことが原因のようでした。
時系列的に整理すると、下記のような状況になっていたようです。

  1. Javaアプリ起動時、Auroraに対して幾つかJDBC接続を確立する
  2. リクエストに応じて、JavaアプリからAuroraにクエリを発行する。この際、Prepareを発行してPrepared Statementを作る。 Javaアプリは、同一のリクエストに対してはPrepared Statementを再利用する。
  3. AuroraのアップデートをZDPで行う。この際、JavaアプリからのJDBC接続は維持されるが、Prepared Statementは全てクリアされる。
  4. Javaアプリに対し、項番2と同様のリクエストを行う。Javaアプリは、コンパイル済みのPrepared Statementが存在しているという認識のまま、これを再利用しようとし、エラーとなる。

同一のアプリに対し、Prepared Statementを利用するもの/しないものを用意してAuroraのアップデートを実施しました。
結果、前者はエラーが発生し、後者はエラーが発生しませんでした。

なお上記の挙動は、独自に調査・検証したものとなります。
現在、AWSの公式見解・ドキュメント等の情報は見つけられておりません。
# 一応、Database Engine Updates 2016-12-14には以下の記載がありますが、これが該当するかどうかは不明です。
# Note that temporary data like that in the performance schema is reset during the upgrade process.

2017/9/26にAWSサポートへの問い合わせを行いました。その後、紆余曲折を経て、2018/1/12に最終回答を頂きました。
コンパイル済みのPrepared Statementが維持されないのは仕様とのことです。

確認した環境・構成

上記事象は、下記構成のJavaアプリで確認しました。

  • Java 8 (Oracle JDK)
  • spring-boot-1.4.0.RELEASE
  • mybatis-spring-boot-starter 1.1.1
  • mariadb-java-client 1.5.5

併せてMyBatisGeneratorも利用しています。
特別な理由がない限り、JavaアプリからはMyBatisGeneratorで生成されたMapperとClassを利用しています。

デフォルトでは、MyBatisGeneratorではPrepared Statementを利用するMapperを生成するようです。

回避策

回避策は概ね以下の3通りになると思います。

1.Prepared Statementを利用しないよう、アプリを変更する。

ソースコード/ORマッパーの改修・設定変更を行い、Prepared Statementを利用しないようにする方法です。
おそらく、この対応は難しいケースがほとんどだと思います。

2.MySQL接続ドライバの設定で、Prepared Statementを利用しないよう変更する。 

今回のケースでは、MariaDB Connector/Jを利用しており、オプションを指定することでPrepared Statementを利用しないように変更することができました。

useServerPrepStmtsオプションをfalseにすることで実現可能です。
ちなみに、1.6.0以降のバージョンはデフォルトでfalseになっているようですので、これ以降のバージョンを利用してる場合は、本件の影響を受けません。

About MariaDB Connector/J -> Optional URL parameters -> Essential options
https://mariadb.com/kb/en/library/about-mariadb-connector-j/

3.ZDPではない、通常のアップデートを実施する

Auroraインスタンスの再起動を伴う、通常のアップデートを実行することで、本件事象を回避することが可能と考えられます(※未検証)
20~30秒程度のダウンタイムが発生します。

下記に、ZDPにならないケースについて記載がありますので、このどれかを満たせば通常のアップデートになると推測できます(※未検証)

Database Engine Updates 2017-08-07 -> Zero-Downtime Patching
http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.DatabaseEngineUpdates.20170807.html

  • Long-running queries are in progress
  • Open long-running transactions exist
  • Binary logging is enabled
  • Binary log replication is running
  • Pending parameter changes exist
  • Temporary tables are in use
  • Table locks are in use
  • Open SSL connections exist

まとめ

DBへのConnection Poolを利用し、且つPrepared Statementを利用するようアプリを実装していると、不具合が発生する可能性が高いです。

経験的な感覚ですが、JavaアプリはConnection Poolを利用しているケースが多いかと思います。
Aurora(MySQL)を利用している場合は、チェックをした方が良いかと思います。

検証作業について

古いClusterバージョンのAuroraインスタンスを作ることはできません。AWSサポートにも聞いてみましたが無理なようでした。
従って、運良く過去に構築した古いAuroraインスタンスが存在していれば検証は可能ですが、それ以外のケースでは検証手段がありません。

40
23
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
23