ロック エスカレーション=悪ではない(ロック エスカレーションの真実) SQL Server

■ ロック エスカレーションとは
行単位のロック(行レベル ロック)は、同時実行性は高まりますが、大量の行が更新される場合には、ロック数が膨大になってしまいます。したがって、SQL Server の場合は、行単位やページ単位など、小さい粒度のロックが大量に発生し、SQL Server 自身に負荷が高いと認識したときには、必要に応じてロックの粒度を拡大(エスカレート)します。この機能のことを「ロック エスカレーション」(Lock Escalation)と呼んでいます。
例えば、テーブル データが 100万件あり、そのうちの 90万件へ行ロックがかかっているとします。このとき、これらのロックをテーブル単位のロックへエスカレートできるのであれば、ロックは 1つで済むのです。なお、SQL Server の場合にロックがエスカレートされるかどうかは、同時実行されているトランザクションや、利用できるメモリ量に依存します。


■ ロック エスカレーション=悪ではない
ラクル社の影響からか、「ロック エスカレーション=悪」という風潮が世の中にはありますが、ロック エスカレーションは悪ではありません。確かにロック エスカレーションは、同時実行性が低下する可能性があるという悪い面がありますが、前述したような良い面もあるのです。したがって、処理によっては、ロック エスカレーションが起きてくれたほうが性能向上しますし、実際、過去の弊社の案件ではロック エスカレーションを活用して性能向上させたことがあります。
ラクル社は、「他社データベースはロック エスカレーションが悪さをする」と言ってさんざん不安を煽っていますが、逆に「Oracle Database にはロック エスカレーション機能がない」ので、これはマイナス要素です。Oracle Database ではロック エスカレーションによる性能メリットを享受することができないのです
Oracle Database は、既定では「行レベル ロック」なので、大量のデータを処理する場合に、大量の行レベル ロックがかかるオーバーヘッドがあります。
これに対し、ロック エスカレーション機能が実装されているデータベース(SQL Server など)では、大量のデータを処理する場合には、自動的にロックをかける粒度を大きくしてくれます。もし、その粒度が大きすぎて同時実行性が落ちるなら、ヒントで粒度を小さく指定すれば良いのです。また、SQL Server でロック エスカレーション機能が不要な場合は、禁止することもできます。


いずれにしても、ロック エスカレーション機能を実装していようがいまいが、性能向上を実現するためには、Oracle であろうと SQL Server であろうと、既定の動作に頼ることは良くないということです。
これは、ロック エスカレーションに限った話しではなく、どんな技術でも同じです。どんな技術にも良い面と悪い面がありますし、他の技術とのトレードオフが発生する場合もあるでしょう。
例えば、トランザクション ログ(REDO ログ)は、障害対策のためには重要なものですが、性能面ではオーバーヘッドがあります。性能を向上させたければ、データベースを利用しなければ良いのです(でも障害対策などが必要になる場合は、別の手段が必要になるので、開発コストなどを考慮すると結局データベースを利用するほうが良いという結論になることが多いと思います)。


■ オラクル社に物申す
ラクル社の人たちは、SQL Server はロック エスカレーションが発生してしまう、とよく叩いていることがありますが、それは間違っています。ロック エスカレーションは禁止することができますし、処理によってはロック エスカレーションが発生してくれた方が性能向上するからです。オラクル社の人たちは、不安を煽っているだけの、単なる(Oracke Database を売りたいだけの)セールス トークをしているにすぎません(buzzword として使っているだけです)。営業さんによっては SQL Server にロック エスカレーションの禁止オプションがあることを知らないケースもあります(技術力不足)。


いずれにしても、セールス トークの場合は、競合製品の技術的な悪い面だけを叩き、自社製品の良い面だけを持ち上げますので、持ち上げられた良い面だけを見るのではなく(セールス トークを鵜呑みにするのではなく)、エンジニアとしては悪い面にも目を向けることが重要です。