SQL Server on Linux では、Linux 特有の動作として OOM Killer があり、Windows 版とは異なるメモリ設定を意識しておく必要があります。
これについては、次のドキュメントで詳細に解説されています。
- How to safeguard SQL Server on Linux from OOM-Killer
- Performance best practices and configuration guidelines for SQL Server 2017 on Linux
本投稿では、これらのドキュメントの内容についてまとめてみたいと思います。
Contents
■SQL Server on Linux のデフォルトのメモリ設定
SQL Server on Linux はデフォルトでは、SQL Server に割り当てるメモリが「80%」として設定されており、この設定による制御により、「SQL Server が利用可能な全体のメモリサイズ」に変化が出てきます。
これについては、ベストプラクティスにも記載されています。
Advanced Configuration
The following recommendations are optional configuration settings that you may elect to perform after installation of SQL Server on Linux. These choices are based on the requirements of your workload and configuration of your Linux Operating System.Set a memory limit with mssql-conf
In order to ensure there is enough free physical memory for the Linux Operating System, the SQL Server process uses only 80% of the physical RAM by default. For some systems which large amount of physical RAM, 20% might be a significant number. For example, on a system with 1 TB of RAM, the default setting would leave around 200 GB of RAM unused. In this situation, you might want to configure the memory limit to a higher value. See the documentation on the mssql-conf tool and the memory.memorylimitmb setting that controls the memory visible to SQL Server (in units of MB).
When changing this setting, be careful not to set this value too high. If you do not leave enough memory, you could experience problems with the Linux Operating System and other Linux applications.
設定については、「mssql-conf」ツールで変更することができ、大容量のメモリを登載している環境では、20% はかなりのサイズになりますので、登載しているメモリのサイズに応じて、SQL Server が使用するメモリの調整を検討します。
mssql-conf の memory.memorylimitmb を過度に設定してしまうと、Linux OS 上の挙動にも影響してきますので、この設定についてはある程度余裕を持たせることは意識しておいた方がよいかと。
設定変更は次のようなコマンドで実施できます。(設定変更後は、SQL Server のサービスの再起動が必要です)
sudo /opt/mssql/bin/mssql-conf set memory.memorylimitmb 4096 # 設定 sudo /opt/mssql/bin/mssql-conf unset memory.memorylimitmb # 設定解除
これで、SQL Server が利用するメモリの全体を調整し、その上で「max server memory」を使用してさらに調整を行うというのが、SQL Server on Linux のメモリ設定方法の基本となります。
■OOM Killer についての考慮
Linux では OOM Killer という挙動が存在しており、メモリやスワップが不足した場合は、OOM のスコアに応じて、プロセスが強制的に終了されるというような動作が行われるようです。
この辺の概念は、Windows とは異なるところですね。
SQL Server のプロセスのスコアについては、次のようなコマンドで確認できます。
pgrep sqlservr | while read pid;do cat /proc/$pid/oom_score;done
SQL Server on Linux は、2 つのプロセスが起動する構成となっています。
PID が小さいものが、PAL Monitor というような、PAL のモニタリング等を実施しているプロセスとなり、PID が大きいものが、実際の SQL Server のプロセスとなります。
メモリの使用状況を見ると「3315」ではなく「33172」のプロセスでメモリを消費している (67.8%) 事が確認できますね。
この辺のプロセス構造は、Oracle と大きな違いになるのでしょうね。
最近、SQL Server 2017 on Linux- Processes という記事で、SQL Sever と Oracle のプロセスの比較を読みました。
Oracle は複数のバックグラウンドプロセスが起動していますが、SQL Server は、一つのプロセスの中で複数の役割のスレッドを実行する構造となっているため、OOM Killer が発生した場合の影響が、異なってくるのでしょうね。
SQL Server の場合は、OOM Killer により、SQL Server のプロセスが終了されると、SQL Server 全体が終了されることになりますので。
プロセスが、OOM Killer によって終了させられると、syslog に次のような出力が出ているかと。
cat /var/log/syslog | grep -i kill Dec 4 11:03:54 ubuntu kernel: [44564.849461] sqlservr invoked oom-killer: gfp_mask=0x24201ca, order=0, oom_score_adj=0 Dec 4 11:03:54 ubuntu kernel: [44564.849497] [<ffffffff81190dd2>] oom_kill_process+0x202/0x3c0 Dec 4 11:03:54 ubuntu kernel: [44564.849669] Out of memory: Kill process 70006 (sqlservr) score 939 or sacrifice child Dec 4 11:03:54 ubuntu kernel: [44564.850830] Killed process 70006 (sqlservr) total-vm:5019052kB, anon-rss:3762360kB, file-rss:0kB
OOM Killer の対応としては、優先度を調整させ、SQL Server が対象外となるようなことも検討できるかもしれません。
たとえば、次のようなコマンドを実行してみます。
pgrep sqlservr | while read pid;do echo -1000 > /proc/$pid/oom_score_adj;done
これにより、スコアの調整がされ、SQL Server のプロセスが OOM Killer の対象となることを防ぐことができますが、あまりにもメモリ使用量が増えている場合には、OS 自体の安定性にも影響を与えることになりますので、このような方法で制御するのは推奨されないような気がします。
Windows 版の場合は、「LPIM」(Lock Page in Memory) により、「ワーキングセットのトリミング」をすることで、SQL Server が確保したメモリのページアウトを防ぐというようなアプローチをすることがありますが、SQL Server on Linux では、このような対応ができないのではと思います。
そこで OOM Killer の対応としては、「mssql-conf ツールによるメモリサイズの適切な設定」+「Swap ファイルによるスワップ領域の確保」が、基本的な対応になるのではないでしょうか。
■Azure の仮想マシンで動作せる場合に実施しておきたいこと
「SQL Server on Linux では、Swap 領域を使用する設定を必ず実施し、Azure 仮想マシンでは、最初にスワップファイルを作成する」ということを実施するということを意識しておくとよいかと。
Ubuntu の場合ですが、デフォルト設定でインストールをすると、Swap が確保された状態でインストールが行われます。
Azure の仮想マシンにも SQL Server インストール済みの Ubuntu のイメージが用意されていますが、これをデプロイした後に、Swap の状態を確認してみます。
top コマンドの実行結果がこちらになりますが、「swap」 がない状態になっていますね。
Azure の Linux イメージでは、初期設定で Swap ファイルが存在していない状態になっています。
- 既成の Linux イメージを実行する Windows Azure 仮想マシンのスワップ領域 ? パート 1
- Windows Azure の Linux 仮想マシンにおけるスワップ領域 ? パート 2
Ubuntu の場合、Linux エージェントの設定を変更することで Swap ファイルをローカルディスクに自動的に作成するように設定することができます。
- Linux のスワップ ファイル
- AzureSwapPartitions
- How to add a swap file in Linux Azure virtual machines
- How to: Add SWAP to Linux VM’s on Azure
実際には次のようなコマンドを実行することで、設定を変更することができます。
sed -i -e "s/ResourceDisk.Format=n/ResourceDisk.Format=y/g" /etc/waagent.conf sed -i -e "s/ResourceDisk.EnableSwap=n/ResourceDisk.EnableSwap=y/g" /etc/waagent.conf sed -i -e "s/ResourceDisk.SwapSizeMB=0/ResourceDisk.SwapSizeMB=4096/g" /etc/waagent.conf
設定が終わったら、Linux エージェントを再起動させます。
systemctl restart walinuxagent
これで、スワップファイルが作成されます。
Top ファイルで認識されていますね。
次のコマンドで利用状況を確認してみます。
pgrep sqlservr | while read pid;do cat /proc/$pid/status | grep VmSwap;done
スワップファイルが設定されていない場合は、0KB となっています。
スワップファイルが設定されている状態であれば、SQL Server がスワップファイルを使っていることが確認できますね。
スワップファイルについては、ベストプラクティスに次のように記載されています。
swapfile
Ensure you have a properly configured swapfile to avoid any out of memory issues. Consult your Linux documentation for how to create and properly size a swapfile.
Windows で SQL Server を実行した場合にページングファイルについては、用途としてはメモリダンプを出力する要素の意味が強い気がしますが、SQL Server on Linux の場合、スワップファイルは SQL Server を安定的に稼働させるために必須となりますので、スワップ話の状態ではなく、必ず作成して SQL Server を動作させるというのは意識しておくとよさそうです。
(スワップファイルの有り無しで、メモリを上限まで使っている際の安定度が全く変わってきますので)
Windows と Linux の違いを含めていろいろとスキルアップデートが必要ですね。