LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログ

複数バージョンを跨ぐPostgreSQLのバージョンアップとAuroraへの移行

データベース移行後記

技術開発部の杉山です。 先日、弊社のAdvent Calenderで書かせて頂いた、Pg_pool+ReplicationからAurora PostgreSQLへの移行が完了しました。 同様にEOL済みのPostgreSQLから少し新しいPostgreSQLへの移行や、Auroraへの移行を検討されている方の参考になればと思い後記に残す事にしました。

techblog.lclco.com

メジャーバージョンのEOLステータス

弊社で利用していた、PostgreSQLは9.xでしたのでFirst Releaseから既に5年以上の月日が経っていて、Final Releaseも既に終了している状態でした。 MySQLの場合もPostgreSQLの場合もリリースから5年間はメンテナンスが続けられているので安心なのですが、最新版の利用は常にバグと向き合う必要があるので、 今回もやはり最新版の採用は避ける事にしました。補足ですが、MySQLの場合は有償版もあるので、そちらでメンテナンスが続けられているので、 コミュニティ版もExtend Supportの影響を受けて、5年目以降もメンテナンスリリースが継続的に提供されている傾向にあります。 詳細に関しては、MySQL :: MySQL テクニカル・サポートを参照頂ければと思います。余談ですが、MySQL5.6も等々今月でSustaining Support期間に入ったので、 もう追加リリースは無くなってしまいました。

PostgreSQLのリリースに関しては以下のリストを参照

f:id:oss-rdbms:20210211075319p:plain 参照:PostgreSQL: Versioning Policy

データベースバージョンアップ

前職ではMySQLのバージョンアップを実施したのですが、やはり移行後はオプティマイザーの挙動の変更等で移行後も少々苦労しましたが、 今回のPostgreSQLのバージョンアップは大きくメジャーバージョンを跨いだにも関わらず、それ程大きな問題は発生しませんでした。 有難い事に、弊社ではシンプルなオブジェクト設計とSQLで運用していて、あまり複雑な利用の方法をしてなかったのが大きな要因だと思っています。 もし皆さんが、移行される場合は十分に検証下さい。

gihyo.jp

  • 2021年2月現在、Aurora PostgreSQL互換で利用可能なバージョン
ubuntu:$  aws rds describe-db-engine-versions --engine  aurora-postgresql --query 'DBEngineVersions[].EngineVersion' --output table
--------------------------
|DescribeDBEngineVersions|
+------------------------+
|  9.6.3                 |
|  9.6.6                 |
|  9.6.8                 |
|  9.6.9                 |
|  9.6.11                |
|  9.6.12                |
|  9.6.16                |
|  9.6.17                |
|  9.6.18                |
|  9.6.19                |
|  10.5                  |
|  10.6                  |
|  10.7                  |
|  10.11                 |
|  10.12                 |
|  10.12                 |
|  10.13                 |
|  10.14                 |
|  11.4                  |
|  11.6                  |
|  11.7                  |
|  11.8                  |
|  11.9                  |
|  12.4                  |
+------------------------+

事前確認と検証

事前に確認しただけでも、60以上のパラメータ変更が存在しましたが、基本的にはDBパラメータはどのデータベースでもDefaultで一般的なDefault値が設定されていて、 初期段階で変更すべきものは多くは無いので、問題になりそうなパラメータだけに焦点を絞って対応しました。 PostgreSQLでも300程度のパラメータがありましたし、MySQL8.0においては500以上のパラメータが存在します。一つ一つ設定しても意味が無いので、 バッファー、メモリー、ロック等の挙動だけしっかり設定しておいて、あとは困ったら都度設定で宜しいかと思います。 関数の実行結果にも、それなにに変更があったので主なSQL処理に関しては、該当関数を利用している部分に関しては実際に実行して結果を比較し、 多数存在するバッチ処理に関しては、適宜エラーや処理結果を可能な範囲で確認しました。

例) 変更の有ったパラメータ
Introduced in 9.4     jit_inline_above_cost                  
Introduced in 9.4    jit_optimize_above_cost                
Introduced in 9.4    jit_profiling_support                  
Introduced in 9.4    jit_provider                           
Introduced in 9.4    jit_tuple_deforming                    
Introduced in 9.4    log_directory                          
Introduced in 9.4    log_replication_commands               
Introduced in 9.4    max_logical_replication_workers        
Introduced in 9.4    max_parallel_maintenance_workers       
Introduced in 9.4    max_parallel_workers                   
Introduced in 9.5    enable_partitionwise_join              
Introduced in 9.5    force_parallel_mode                    
Introduced in 9.5    gin_pending_list_limit                 
Introduced in 9.5    huge_pages                             
Introduced in 9.5    idle_in_transaction_session_timeout    
Introduced in 9.5    jit                                    
Introduced in 9.5    jit_above_cost                         
Introduced in 9.5    jit_debugging_support                  
Introduced in 9.5    jit_dump_bitcode                       
Introduced in 9.5    jit_expressions                        
Introduced in 9.6    backend_flush_after                    
Introduced in 9.6    bgwriter_flush_after                   
Introduced in 9.6    checkpoint_flush_after                 
Introduced in 9.6    cluster_name                           
Introduced in 9.6    data_sync_retry                        
Introduced in 9.6    dynamic_shared_memory_type             
Introduced in 9.6    enable_gathermerge                     
Introduced in 9.6    enable_parallel_append                 
Introduced in 9.6    enable_parallel_hash                   
Introduced in 9.6    enable_partition_pruning               
Introduced in 9.6    enable_partitionwise_aggregate         
Introduced in 10     ssl_passphrase_command_supports_reload 
Introduced in 10     ssl_prefer_server_ciphers              
Introduced in 10     syslog_sequence_numbers                
Introduced in 10     syslog_split_messages                  
Introduced in 10     track_commit_timestamp                 
Introduced in 10     vacuum_cleanup_index_scale_factor      
Introduced in 10     wal_compression                        
Introduced in 10     wal_consistency_checking               
Introduced in 10     wal_log_hints                          
Introduced in 10     wal_retrieve_retry_interval            
Introduced in 10     wal_writer_flush_after                 
Introduced in 11     max_parallel_workers_per_gather        
Introduced in 11     max_pred_locks_per_page                
Introduced in 11     max_pred_locks_per_relation            
Introduced in 11     max_replication_slots                  
Introduced in 11     max_sync_workers_per_subscription      
Introduced in 11     max_wal_size                           
Introduced in 11     max_worker_processes                   
Introduced in 11     min_parallel_index_scan_size           
Introduced in 11     min_parallel_table_scan_size           
Introduced in 11     min_wal_size                           
Introduced in 11     old_snapshot_threshold                 
Introduced in 11     operator_precedence_warning            
Introduced in 11     parallel_leader_participation          
Introduced in 11     parallel_setup_cost                    
Introduced in 11     parallel_tuple_cost                    
Introduced in 11     row_security                           
Introduced in 11     session_preload_libraries              
Introduced in 11     ssl_dh_params_file                     
Introduced in 11     ssl_ecdh_curve                         
例) 処理結果の違い

❶ to_char() 関数で日付時間のテンプレートパターンについて、マイナス記号をフィールド幅の一部として数えなくなりました。 その為、期待される出力結果が変わることになります。

f:id:oss-rdbms:20210212125956p:plain

❷ json #> text[ ] 演算子で、右辺に空配列を与えた場合に、NULL ではなく、左辺値全体が返るようになりました。

f:id:oss-rdbms:20210212130148p:plain

❸ <=、>=、<> の優先順位が <, >、= と同じに下げられました。
備考: operator_precedence_warning で異なった解析結果の警告を確認可能。

f:id:oss-rdbms:20210212130239p:plain

検証前には以下サイトを参考にさせて頂きました。「感謝」

PostgreSQL 9.4 に関する技術情報
PostgreSQL 9.5 に関する技術情報
PostgreSQL 9.6 に関する技術情報
PostgreSQL 10 に関する技術情報
PostgreSQL 11 に関する技術情報

パタメータの詳細等はこちらを活用させて頂きました。

postgresqlco.nf

余談ですが、こちらのサイトは素晴らしいのですが、
EOLした製品の翻訳を見ると思わず苦笑いしてしまいます。

f:id:oss-rdbms:20210211083636p:plain

バージョンを大きく跨ぐ場合はやはり論理バックアップ

メジャーバージョン1世代程度であれば、メンテナンス時間は殆ど取らずにバージョンアップ出来ますが、 大幅にメジャーバージョンを跨ぐバージョンアップの場合は、どうしても互換性、全体的な工数、コストを考えるとメンテナンス時間を取って、 一気にテキストフォーマットでデータベースのバックアップを取得し、リストアする為のメンテナンス作業が必要になってしまいます。 安定稼働している状況のままにしておきたい気持ちもありますが、定期的にバージョンアップしておけば、サービス停止時間が殆ど発生しない、 若しくは最小限に留める事が可能です。また、定期的なバージョンアップで、”will be deprecated"のメッセージにも気付く事が出来るので、 計画的なパラメータや構成の変更が可能です。

pg_dump -Fp -f <ダンプファイル名> <データベース>
備考:

Auroraでは基本的に、パブリックスキーマはマスターユーザーやデータベース所有者ではなく 、 rdsadmin によって所有されているので変更したい場合は以下を参考に調整下さい。

aws.amazon.com

Auroraでのパラメータ調整

AuroraではDB クラスターパラメータグループとDB パラメータグループにてデータベースインスタンスのパラメータを調整します。 DB クラスターパラメータグループは、Aurora DB クラスター内のすべての DB インスタンスに適用されるエンジン設定値のコンテナとして機能し、 DB パラメータグループは、1 つ以上の DB インスタンスに適用されるエンジン設定値のコンテナとして機能します。その為、DBパラメータグループを利用して、 クラスターグループ内のインスタンスに個別のパラメータを設定する事が可能です。基本的にフェールオーバーを考慮すると、書き込みと読み込みデータベースに関しては、同じパラメータを適用する事が多いかと思います。 それぞれのパラメータの優先順位に関しては、Class Method様のブログで検証されていたので、詳細に関してはそちらを参考にしてみて頂ければと思います。

docs.aws.amazon.com

dev.classmethod.jp

タイムゾーンのカスタマイズ

AuroraはDefaultでUTCに設定されているので、弊社では国内のユーザー様向けのサービスを提供させて頂いているのと、 もともとデータベースに格納される時間はJSTで運用していたので、レポート等の調整等を考えるとJSTにする必要がありました。

postgres=>  show timezone;
  TimeZone  
------------
 Asia/Tokyo
(1 row)

postgres=>  SHOW client_encoding;
 client_encoding 
-----------------
 UTF8
(1 row)

f:id:oss-rdbms:20210211095330p:plain

ロック・タイムアウトのカスタマイズ

また、PostgreSQLのdead lockはDefaultで1秒と、とても短いのでそちらも合わせて変更致しました。 それ以外には、work_mem等のメモリー設定を弊社の処理内容に合わせて変更。但し、shared_buffersに関しては、「Auroraにて最適化されているので変更しない方が良い」とのアドバイスを、 PostgreSQLユーザ会の壮大さん含め、知見のある皆様からアドバイス頂いたので変更せずDefaultのままにしました。

postgres=> select name,setting,unit,context,category,short_desc from pg_settings where name like '%dead%';
-[ RECORD 1 ]-------------------------------------------------------------
name       | deadlock_timeout
setting    | 600000
unit       | ms
context    | superuser
category   | Lock Management
short_desc | Sets the time to wait on a lock before checking for deadlock.

postgres=> 

移行直後の負荷発生について

データベース移行後にAuroraにてCPU負荷が極端に高くなる事象が発生してしまいました。 弊社の優秀なSREがPerformance Insightsを設定しておいてくれたおかげで、TOP10SQLを即時に確認する事が出来、 直ぐに対応する事が出来ました。データベースを長らく触っていますが、SETステートメントが原因で負荷が上昇するという事は経験が無かったので、 半信半疑でしたが、他にも目立った原因が見当たらず対応して頂いたら負荷が落ち着いてきました。感謝。 確認したところ、同様の事例が報告されていたとの事。但し再現が出来ず、根本的な原因は分かっていな状況との事。なので、現状でも何故だか根本的原因は不明です。 もし、皆さんの環境でも同様の現象が発生したら、確認してみて頂くのも良いかもしれません。

f:id:oss-rdbms:20210211102546p:plain

設定が必要な場合は、パラメータグループでstatement_timeoutを設定する事で回避可能。 docs.aws.amazon.com

最後に

上記の負荷もあり、微妙にメンテナンス時間が伸びてしまいましたが、現状特に問題無く安定稼働しております。 暫く運用してから問題に気付くケースも多々あるので、当面の間は普段よりも気を配りながら運用して行こうと思います。 ただ、スケールアップ、スケールダウン、フェールオーバーを一時的な負荷に対応する為に実施しましたが、非常にスムーズに実施出来たので、 バージョンアップ含めて、今後の運用が格段に楽になる事は間違いないので非常に前向きなメンテナンスに出来たかと思います。 あとは、引き続きパフォーマンス・工数・コスト含めて注視しながら、全体的にメリットが多かった事を再確認出来たら、対応が成功だったと振り返る事が出来るかと考えています。

採用情報

LCLではエンジニアのアイデアを生かして、更にサービスを盛り上げて行こうと思ってます!! 引き続き、生産性向上に励む仲間を募集中です。

www.lclco.com