Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
約6年前投稿

MySQLデータベースパフォーマンスのためのLinux OSチューニング

Percona Database Performance Blogの翻訳。Linux上でMySQLサーバを運用する際の、カーネル、ファイルシステム、メモリなどのチューニングのポイントをまとめた記事。

原文
Linux OS Tuning for MySQL Database Performance - Percona Database Performance Blog (English)
原文著者
Spyros Voultepsis
原文公開日
2018-07-03
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665 B5aa4f809000b9147289650532e83932
翻訳者
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
翻訳レビュアー
B5aa4f809000b9147289650532e83932 taka-h
原著者への翻訳報告
2255日前 原文へのコメントで報告済み 編集


この記事では、MySQLデータベースサーバーのパフォーマンスチューニングと最適化のために調整する重要なLinuxの設定を復習します。OSのチューニングに使うLinuxのパラメータのいくつかは、物理サーバーか、仮想サーバーか、クラウドかというシステムの種類ごとに異なりますが、それがどう異なるかについても触れます。MySQLのパラメータについては、Alexanderの「インストール直後のMySQL 5.7パフォーマンスチューニング(MySQL 5.7 Performance Tuning Immediately After Installation)」というブログなど他の記事で扱います。その記事はMySQL 5.7や8.0といった最新バージョンに強く関連した内容ですが、この記事ではデータベースパフォーマンスに影響を及ぼしうるLinuxのOSパラメーターについて焦点を当てていきます。

サーバーとOS

データベースのパフォーマンスを改善したい時に確認の上変更を検討すべきLinuxのパラメータです。

カーネル - vm.swappiness

これは、メモリーページをスワップアウトする度合いを表す値です。十分にRAMを持ったサーバでは、この値はできる限り小さくしておくべきでしょう。余計なI/Oはサービスのスローダウンやサービス停止を引き起こしかねません。0に設定するとスワップを完全に無効にし、1にするとカーネルは最低限のスワップしか行いません。大抵は1に設定すればよいでしょう。

# rootでswappinessを設定
echo 1 > /proc/sys/vm/swappiness
# あるいは代わりにsysctlを使用して設定
sysctl -w vm.swappiness=1
# 設定が変更されたのを確認
cat /proc/sys/vm/swappiness
1
# sysctlでも確認できます
sysctl vm.swappiness
vm.swappiness = 1

設定は /etc/sysctl.conf に永続化も可能です。

vm.swappiness = 1

ファイルシステム XFS/ext4/ZFS

XFS

XFSは高いスケーラビリティーを実現するために設計された、ハイパフォーマンスなジャーナリングファイルシステムです。XFSは、ファイルシステムが複数のストレージデバイスにまたがっている場合も含め、ネイティブに近いI/Oパフォーマンスを発揮します。また、8EiBまでのファイルサイズをサポートし、非常に大きいファイルシステムに向いた機能も持っています。リカバリが速く、トランザクションも高速で、フラグメンテーションを減らす遅延アロケーションや、DIRECT I/Oによるraw I/Oに近いパフォーマンスもサポートされています。

mkfs.xfsのデフォルトオプションは最適な速度になる優れた設定なので、シンプルに

# デフォルトのmkfsオプションを使用
mkfs.xfs /dev/target_volume

を実行すれば、データの安全性を確保しつつ最高のパフォーマンスが得られます。マウントオプションについては、ほとんどのケースでデフォルトのまま使用できます。ファイルシステムによっては、/etc/fstabnoatimeマウントオプションを追加するとパフォーマンスの向上があるでしょう。XFSでのatimeのデフォルトの挙動は、noatimeと比べてほとんどオーバーヘッドがなくatimeと同じ値を保持するrelatimeになります。バッテリーバックアップ付きで不揮発性のLUN上にXFSでファイルシステムを作ったら、nobarrierマウントオプションをつけてライトバリアーを無効化することで、必要以上にデータをフラッシュすることがなくなるので、ファイルシステムのパフォーマンスをさらに改善できます。BBU(backup battery unit)がない、あるいはあるかどうか分からないなら、バリアーはそのままにしておいて、データの一貫性を台無しにすることのないようにしましょう。このオプションを有効にするなら、/etc/fstabは以下のようになります。

/dev/sda2              /datastore              xfs     defaults,nobarrier
/dev/sdb2              /binlog                 xfs     defaults,nobarrier
ext4

ext4は、パフォーマンス改善を加えてext3の後継として開発されてきました。ほとんどのワークロードに合った、間違いのないファイルシステムの選択肢です。16TBまでというxfsよりも小さなファイルサイズしかサポートしていない点に注意しましょう。テーブルスペースのサイズが非常に大きかったり、大きくなる場合は注意する必要がある点です。データの一貫性をリスクにさらさず堅牢なファイルシステムを使うには、デフォルト設定を推奨します。しかし、BBUキャッシュがあるエンタープライズ向けストレージコントローラーを使っている場合、以下のマウントオプションで最高のパフォーマンスが得られるでしょう。

/dev/sda2              /datastore              ext4     noatime,data=writeback,barrier=0,nobh,errors=remount-ro
/dev/sdb2              /binlog                 ext4     noatime,data=writeback,barrier=0,nobh,errors=remount-ro

注意 : data=writebackオプションによって、実際のファイルデータを除いたメタデータだけがジャーナリングされます。突然の電源停止の際、最近変更されたファイルが壊れる可能性があります。ただし、BBUが有効なコントローラーがある時にはそのリスクは低くなります。nobhdata=writebackオプションが有効な時だけ意味があります。

ZFS

ZFSは、データの保護と破損のバランスを取った、ファイルシステムとLVMを組み合わせたエンタープライズストレージソリューションです。ZFSの豊富な機能セットが、採用を考える際の重要な項目になるケースは確かにあって、中でも高度なボリューム管理が必要条件の際はそうです。MySQL向けのZFSチューニングは複雑なトピックなので、このブログの対象からは外れます。詳しい情報は、Yves Trudeauによってこのトピックについて書かれたブログ記事を参照してください。

ディスクサブシステム - I/Oスケジューラー

ほとんどのモダンなLinuxディストリビューションでは、デフォルトでnoopdeadline I/Oスケジューラが設定されていて、これらはどちらもcfqanticipatoryよりもいいパフォーマンスが出ます。しかし、各デバイスのスケジューラーをいつもチェックするのはいい習慣です。もしnoopあるいはdeadline以外のスケジューラーが設定されていたら、サーバーを再起動することなくポリシーを変更できます。

# I/Oスケジューラーの設定を確認。角かっこに入っている値が実行中のスケジューラー
cat /sys/block/sdb/queue/scheduler
noop deadline [cfq]
# 設定を変更
sudo echo noop > /sys/block/sdb/queue/scheduler

設定を永続化するには、GRUB設定ファイルを変更する必要があります。

# この行を変更
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
# 変更後は以下のようにする
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash elevator=noop"

AWSでの注意 : I/Oスケジューラーがnoneになるケースがあり、その一番の例がEBSボリュームがNVMeブロックデバイスであるAWS VMインスタンスタイプの場合です。これは、モダンなPCIe/NVMeデバイスではこの設定が使われないためです。このようなデバイスは内部に非常に大きなキューを持っており、I/Oスケジューラーをバイパスしてしまうのが理由です。この場合、そのようなディスクに最適なよう、設定はnoneになります。

ディスクサブシステム - ボリューム最適化

可能であれば、OS、binlog、データ、redo logはそれぞれ異なるディスクボリュームを使うのが理想的です。論理的に分けるだけでなく物理的にOSとデータパーティションを分けることで、データベースのパフォーマンスはよくなります。RAIDレベルもパフォーマンスに影響があります。チェックサムの整合性を保つのにコストがかかるので、RAID-5は避けた方がよいでしょう。冗長性を妥協せずに最高のパフォーマンスを得るには、バッテリーバックアップされたキャッシュユニットを持った高度なコントローラーを使い、できれば複数のディスクにまたがったRAID-10ボリュームを使いましょう。

AWSでの注意 : EBSボリュームやAWSのストレージ最適化についての詳しい情報は、以下のリンクにあります。

データベース設定

システムアーキテクチャ - NUMAの設定

Non-Uniform Memory Access (NUMA)とは、SMPなシステムのプロセッサーから見て、ローカルでないメモリー(他のCPUに割り当てられたメモリー)よりもローカルなメモリーに高速にアクセスできるというメモリーデザインのことです。これにより、データベースのパフォーマンスが最適な状態でなくなったり、スワップが発生したりする可能性があります。ノードのローカルなRAMのサイズよりもバッファプールのメモリー割り当てが大きく、かつメモリアロケーションポリシーがデフォルトの場合、スワップが発生します。NUMAが有効なサーバーは、CPUノード間でそれぞれ異なるノード距離(node distance)を通知してきます。無効なサーバでは、1種類の距離しか通知しません。

# NUMAなシステム
numactl --hardware
available: 4 nodes (0-3)
node 0 cpus: 0 1 2 3 4 5 6 7
node 0 size: 65525 MB
node 0 free: 296 MB
node 1 cpus: 8 9 10 11 12 13 14 15
node 1 size: 65536 MB
node 1 free: 9538 MB
node 2 cpus: 16 17 18 19 20 21 22 23
node 2 size: 65536 MB
node 2 free: 12701 MB
node 3 cpus: 24 25 26 27 28 29 30 31
node 3 size: 65535 MB
node 3 free: 7166 MB
node distances:
node   0   1   2   3
  0:  10  20  20  20
  1:  20  10  20  20
  2:  20  20  10  20
  3:  20  20  20  10

# NUMAが無効な(uniformな)システム
numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3 4 5 6 7
node 0 size: 64509 MB
node 0 free: 4870 MB
node distances:
node   0
  0:  10

NUMAシステム、つまりnumactlがノードごとに違った距離を表示する場合、メモリーインターリーブを避けるためにMySQLのinnodb_numa_interleaveが有効になっている必要があります。Percona Serverでは、flush_caches変数を導入することで、NUMAのサポートを改善しています。これが有効な時は、ノード間の割り当てが公平になるようになります。ノード間で割り当てが均等かどうかを確認するには、スクリプトでmysqldプロセスに対するnuma_mapsを調べてみましょう。

# CPUノードごとのメモリー割り当てを表示するnuma_maps.plというPerlスクリプト
# 3595はmysqldプロセスのpid
perl numa_maps.pl < /proc/3595/numa_maps
N0        :     16010293 ( 61.07 GB)
N1        :     10465257 ( 39.92 GB)
N2        :     13036896 ( 49.73 GB)
N3        :     14508505 ( 55.35 GB)
active    :          438 (  0.00 GB)
anon      :     54018275 (206.06 GB)
dirty     :     54018275 (206.06 GB)
kernelpagesize_kB:         4680 (  0.02 GB)
mapmax    :          787 (  0.00 GB)
mapped    :         2731 (  0.01 GB)

まとめ

この記事では、OSに関係したいくつかの設定を分析し、データベースパフォーマンスの改善のためにどのようにチューニングできるかを説明しました。

Webinarの録画Troubleshooting Best Practices: Monitoring the Production Database Without Killing Performanceもおすすめです。

次の記事
GitHubのRails離れと、迫りくるMicrosoft
前の記事
さようならPython、こんにちはGo

Feed small 記事フィード

新着記事Twitterアカウント