Amazon Auroraのレプリカとバッファキャッシュのウォームアップの関係について確かめてみた

先日、Amazon AuroraのレプリカのAuto Scalingが発表されました。

 * **[Amazon Aurora で Aurora レプリカの Auto Scaling をサポート](https://aws.amazon.com/jp/about-aws/whats-new/2017/11/amazon-aurora-now-supports-auto-scaling-for-aurora-replicas/)**

これに関連する話題である方とツイートのやり取りをしていて、ふと、**「レプリカとバッファキャッシュ（またはバッファプールキャッシュ…MySQLでいうところのバッファプール）について経験則でぼんやりと把握している挙動について再確認してみよう」**と思い立ったので検証してみました（ちょっと雑ですが）。

※今回、Auto Scalingのときの挙動については確認していません。

---

**12/12追記：**
AUto Scalingについても試してみました。

 * **[Amazon Aurora（MySQL互換） Auto Scalingで追加されたレプリカ（Reader）インスタンスのバッファキャッシュのウォームアップはどうなる？](https://qiita.com/hmatsu47/items/6cd12f621fe22ed0cff1)**

---

# 1. 確認する事項

 * プライマリインスタンス（Writer）をスナップショットから復元した時に、バッファキャッシュはウォームアップされているのか？
 * プライマリインスタンス（Writer）を再起動したときに、バッファキャッシュは残っている（※）のか？
 * レプリカインスタンス（Reader）作成時に、バッファキャッシュはウォームアップされているのか？
 * バッファキャッシュ容量変更を伴わないパラメータグループの変更を行って再起動した場合、バッファキャッシュは残っているのか？
 * バッファキャッシュ容量を減らすパラメータグループの変更を行って再起動した場合、バッファキャッシュは残っているのか？
 * プライマリインスタンス（Writer）で更新が発生した場合、レプリカインスタンスのバッファキャッシュは更新される（※）のか？
 * バッファキャッシュ容量を増やすパラメータグループの変更を行って再起動した場合、バッファキャッシュは残っているのか？

---

**11/24追記：**

 * レプリカインスタンス（Reader）を再起動したときに、バッファキャッシュは残っているのか？
 * 手動でフェイルオーバーしたときに、それぞれのインスタンスのバッファキャッシュは残っているのか？

（追記終わり）

---

（※）は仕様として公式にアナウンスされています。

なお、検証に使ったインスタンスタイプはr4.largeです（MySQL互換エディション・バージョン1.15.1）。
以前別の検証を行ったときのテーブルを再利用しています。

```mysql:テーブル定義
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| akptest2           |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql> USE akptest2;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+--------------------+
| Tables_in_akptest2 |
+--------------------+
| dept               |
| member             |
| sales              |
+--------------------+
3 rows in set (0.00 sec)

mysql> DESC sales;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| sales_id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| member_id   | int(10) unsigned | NO   | MUL | NULL    |                |
| total_value | int(10) unsigned | NO   |     | NULL    |                |
| note        | varchar(200)     | YES  |     | NULL    |                |
+-------------+------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
```

今回はこの「akptest2.sales」テーブルを使います。

※レプリカインスタンス（Reader）側では「SHOW ENGINE INNODB STATUS」は「Empty set」となります。また、AuroraではINFORMATION_SCHEMAのバッファプール容量関連の項目は信頼できる値が入らないそうです（サポート確認済み。実際にグラフ描画させたところ、数値の大小関係が異常になった）。

# 2. 結果確認

## 2-1. プライマリインスタンス（Writer）復元時

```mysql:プライマリ復元時／プライマリ側
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 8001683456 |
+-------------------------+------------+
1 row in set (0.00 sec)

mysql> SHOW ENGINE INNODB STATUS\G
（中略）
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 0; in additional pool allocated 0
Dictionary memory allocated 189597
Buffer pool size   488068
Free buffers       487846
Database pages     222
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 15, created 2, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 222, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size   244034
Free buffers       243901
Database pages     133
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 6, created 2, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 133, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
---BUFFER POOL 1
Buffer pool size   244034
Free buffers       243945
Database pages     89
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 9, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 89, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
（後略）

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (5.71 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (0.54 sec)
```

スナップショット復元直後、バッファキャッシュには「akptest2.sales」テーブルのデータは載っていなかったようです。

## 2-2. プライマリインスタンス（Writer）復元時

再起動しました。

```mysql:プライマリ再起動時／プライマリ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW ENGINE INNODB STATUS\G
（中略）
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 0; in additional pool allocated 0
Dictionary memory allocated 206722
Buffer pool size   488068
Free buffers       477146
Database pages     10922
Old database pages 3991
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 0, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 10922, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size   244034
Free buffers       238542
Database pages     5492
Old database pages 2007
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 0, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 5492, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
---BUFFER POOL 1
Buffer pool size   244034
Free buffers       238604
Database pages     5430
Old database pages 1984
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 0, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 5430, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
（後略）

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (0.55 sec)
```

再起動してもバッファキャッシュはちゃんと残っているようです。

※レプリカインスタンスがある場合も同じ結果でした。

但し、以前、データ数百GiB、インスタンスタイプr3.2xlargeのプロダクト環境で試したときに、再起動前と再起動直後でクエリの実行時間が明らかに変わったことがあります。
[こちら](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.Overview.html)のページにも、

> Aurora では、データベースがシャットダウン後に起動したとき、または障害発生後に再起動したときに、バッファプールキャッシュを "ウォームアップ" します。つまり、Aurora では、メモリ内ページキャッシュに保存された既知の一般的なクエリのページを使用してバッファープールを事前にロードします。これにより、通常のデータベースの使用からバッファープールを "ウォームアップ" する必要性をバイパスすることでパフォーマンスが向上します。
>
> Aurora ページキャッシュはデータベースとは別のプロセスで管理されるため、ページキャッシュはデータベースとは無関係に存続できます。データベースに障害が発生した場合でも、ページキャッシュはメモリに残るため、バッファプールはデータベースの起動時に最新の状態にウォームアップされます。

とあるので、再起動後、バッファキャッシュが「ロード」されるまでにタイムラグがある可能性があります（今回は検証できませんでした）。

## 2-3. レプリカインスタンス（Reader）作成時

続いて、レプリカインスタンス（Reader）を作成して、そちらで同じクエリを実行してみます。

```mysql:レプリカ作成時／レプリカ側
mysql> SHOW ENGINE INNODB STATUS\G
Empty set (0.01 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (7.48 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (0.55 sec)
```

挙動（所要時間）から推測すると、作成直後のレプリカインスタンスのバッファキャッシュはウォームアップされていなかったようです。

※2つ目のレプリカインスタンスを作成したときも同様でした。

## 2-4. バッファキャッシュ容量変更を伴わないパラメータグループの変更→再起動時

ここで、コンソールから、バッファキャッシュサイズに実質的に変更が生じないよう数値を指定し、プライマリインスタンスを再起動します。

```mysql:容量変更なし／プライマリ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 8001683456 |
+-------------------------+------------+
1 row in set (0.00 sec)

mysql> SHOW ENGINE INNODB STATUS\G
（中略）
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 0; in additional pool allocated 0
Dictionary memory allocated 206722
Buffer pool size   488068
Free buffers       477146
Database pages     10922
Old database pages 3991
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 0, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 10922, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size   244034
Free buffers       238542
Database pages     5492
Old database pages 2007
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 0, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 5492, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
---BUFFER POOL 1
Buffer pool size   244034
Free buffers       238604
Database pages     5430
Old database pages 1984
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 0, created 0, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 5430, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
（後略）

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (0.55 sec)
```

```mysql:同／レプリカ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 8001683456 |
+-------------------------+------------+
1 row in set (0.00 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (7.17 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (0.55 sec)
```

 * **プライマリインスタンスはバッファキャッシュが維持される**
 * **レプリカインスタンスはバッファキャッシュがクリアされる**

という、興味深い結果になりました。
※複数回試しています。

## 2-5. バッファキャッシュ容量を減らすパラメータグループの変更→再起動時

バッファプールの容量を約1/10に減らして、プライマリインスタンスを再起動します。

```mysql:容量減／プライマリ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 799014912 |
+-------------------------+-----------+
1 row in set (0.00 sec)

mysql> SHOW ENGINE INNODB STATUS\G
（中略）
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 0; in additional pool allocated 0
Dictionary memory allocated 206722
Buffer pool size   48707
Free buffers       48468
Database pages     239
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 238, created 1, written 0
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 239, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
（後略）

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (5.85 sec)
```

```mysql:同／レプリカ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name           | Value     |
+-------------------------+-----------+
| innodb_buffer_pool_size | 799014912 |
+-------------------------+-----------+
1 row in set (0.00 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          125.5085 |
+---------------+----------------+------------------+-------------------+
1 row in set (6.48 sec)
```

この場合は、プライマリ／レプリカインスタンスともバッファキャッシュがクリアされました。

## 2-6. プライマリインスタンス（Writer）更新発生時→レプリカインスタンスは？

プライマリインスタンスで、データを更新してみます。

```mysql:データ更新／プライマリ側
mysql> UPDATE sales SET note='!!Replaced!!' WHERE member_id < 3000;
Query OK, 37740 rows affected (1.24 sec)
Rows matched: 39038  Changed: 37740  Warnings: 0

mysql> SELECT SQL_NO_CACHE DISTINCT(note) FROM sales WHERE member_id < 3000;
+--------------+
| note         |
+--------------+
| !!Replaced!! |
+--------------+
1 row in set (0.13 sec)
```

```mysql:同／レプリカ側
mysql> SELECT SQL_NO_CACHE DISTINCT(note) FROM sales WHERE member_id < 3000;
+--------------+
| note         |
+--------------+
| !!Replaced!! |
+--------------+
1 row in set (0.27 sec)

mysql> SELECT SQL_NO_CACHE DISTINCT(note) FROM sales WHERE member_id < 3000;
+--------------+
| note         |
+--------------+
| !!Replaced!! |
+--------------+
1 row in set (0.12 sec)
```

1回目と2回目の結果に差がありますので、最初からプライマリ側と同じ状態になるとは言い切れませんが（Oldページの容量の関係でしょうか？ステータスが取れないので正確なところはわかりませんが）、時間を見る限り、プライマリ側の更新によって、レプリカ側のバッファキャッシュも更新されているようです。

※この、**バッファキャッシュ更新処理に必要な時間がレプリカラグの要因**、とのことです（ストレージはプライマリ／レプリカで共用しているが、バッファキャッシュは各インスタンスに独立して存在するため）。

## 2-7. バッファキャッシュ容量を増やすパラメータグループの変更→再起動時

容量を初期（デフォルト）の設定に戻して、プライマリインスタンスを再起動します。

```mysql:容量増／プライマリ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 8001683456 |
+-------------------------+------------+
1 row in set (0.01 sec)

mysql> SHOW ENGINE INNODB STATUS\G
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 0; in additional pool allocated 0
Dictionary memory allocated 206722
Buffer pool size   488068
Free buffers       487829
Database pages     239
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 238, created 1, written 0
0.68 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 993 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 239, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
----------------------
INDIVIDUAL BUFFER POOL INFO
----------------------
---BUFFER POOL 0
Buffer pool size   244034
Free buffers       243892
Database pages     142
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 141, created 1, written 0
0.26 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 996 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 142, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
---BUFFER POOL 1
Buffer pool size   244034
Free buffers       243937
Database pages     97
Old database pages 0
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0 single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 97, created 0, written 0
0.42 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 990 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 97, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
（後略）

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          121.2283 |
+---------------+----------------+------------------+-------------------+
1 row in set (5.91 sec)
```

```mysql:同／レプリカ側
mysql> USE akptest2;
No connection. Trying to reconnect...
Connection id:    4
Current database: *** NONE ***

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 8001683456 |
+-------------------------+------------+
1 row in set (0.00 sec)

mysql> SELECT SQL_NO_CACHE AVG(sales_id), AVG(member_id), AVG(total_value), AVG(LENGTH(note)) FROM sales;
+---------------+----------------+------------------+-------------------+
| AVG(sales_id) | AVG(member_id) | AVG(total_value) | AVG(LENGTH(note)) |
+---------------+----------------+------------------+-------------------+
|   500000.5000 |     39956.5803 |       50054.5762 |          121.2283 |
+---------------+----------------+------------------+-------------------+
1 row in set (7.16 sec)
```

ともに、バッファキャッシュはクリアされました。

## 2-8. レプリカインスタンス（単純）再起動時

結果ログは省略しますが、バッファキャッシュは残りました。

## 2-9. フェイルオーバー時

こちらも結果ログは省略しますが、

 * レプリカから昇格したプライマリ側はバッファキャッシュが残る
 * プライマリから降格したレプリカ側はバッファキャッシュがクリアされる

という結果になりました。
※一時「両側とも残ったり残らなかったり不安定」と書きましたが、エンドポイントの入れ替わりを誤認して記録した結果でした。訂正します。

# 3. まとめ

※順番は見やすいように入れ替えました。

| テストケース | 結果 |
|:--|:--|
| プライマリインスタンス（Writer）復元時 | バッファキャッシュはウォームアップされない |
| レプリカインスタンス（Reader）作成時 | バッファキャッシュはウォームアップされない |
| プライマリインスタンス（Writer）再起動時 | バッファキャッシュは残る（公式仕様通り） |
| レプリカインスタンス（Reader）再起動時 | バッファキャッシュは残る（公式仕様通り？） |
| バッファキャッシュ容量変更を伴わないパラメータグループ変更・再起動時 | プライマリ側はバッファキャッシュが残り、レプリカ側はクリアされる |
| バッファキャッシュ容量を減らすパラメータグループ変更・再起動時 | プライマリ側／レプリカ側ともバッファキャッシュはクリアされる |
| バッファキャッシュ容量を増やすパラメータグループ変更・再起動時 | プライマリ側／レプリカ側ともバッファキャッシュはクリアされる |
| プライマリインスタンス（Writer）で更新発生 | レプリカ側のバッファキャッシュは更新される（公式仕様通り） |
| 手動フェイルオーバー時 | 新プライマリ側のバッファキャッシュは残る／新レプリカ側のバッファキャッシュはクリアされる |

バッファキャッシュ容量変更を伴わないパラメータグループ変更・再起動時と、手動フェイルオーバー時だけ、意外な結果となりました。

プライマリインスタンスについてはほぼ予想通りの動きであり管理上の手間は少ないと言えますが、レプリカインスタンスについては、どのタイミングで運用中のクラスタに「再投入」するか、通常のMySQLクラスタを構成する場合と同様の注意が必要です（安易にリーダーエンドポイントを使ってしまうと、「クライアントからの接続がAZ跨ぎになってレイテンシが増加する問題」も発生しうるので、ちょっと辛いですね）。
※おそらく、「DB本体のサービスとは別プロセスとして起動しているバッファキャッシュのサービスがキャッシュをメモリ上に保持している状態で、ストレージに存在するデータとの間で現実的な時間内に（REDOログを使うなどして）確実に整合させることができる（または整合確認ができる）処理ではバッファキャッシュが残り、そうでない処理ではあえて残さずキャッシュデータ全体を無効化している」のだと思います。

なお、障害テスト時の結果については、以下の記事にまとめました。

 * **[Amazon Auroraの障害シミュレーションとバッファキャッシュの維持（ウォームアップ）の関係について確かめてみた](https://qiita.com/hmatsu47/items/886a7d459ed6ca2282bd)**

また、本当はメンテナンスバージョンアップ時の挙動も確かめたいところですが（しばらく稼働させておいて試さないといけないため、テストは難しそう）、おそらく「バージョンアップの内容次第で結果が変わる」のではないかと思います。

---

 * **[Qiitaに投稿したAmazon Aurora関連記事](http://hmatsu47.hatenablog.com/aurora)**