「データの移動が原因でNOLOCKでスキャンを続行できませんでした」を再現する方法


10

NOLOCK一部の大規模なジョブで、「データの移動が原因でスキャンを続行できませんでした」というメッセージが時々表示さWITH (NOLOCK)れます。これは、選択クエリで実行されます。

これは、ページ分割があり、データが本来あるべき場所でなくなったときにデータを選択しようとすることと関係があることを理解しています。それが私の環境で起こっていることだと思います。

これをどのように再現しますか?

短期的な回避策を講じてエラーをキャッチし、これが発生したときに再試行しようとしていますが、再現できない場合はテストできません。これを引き起こす合理的に信頼できる方法はありますか?

それが発生した場合、クエリを再度実行すると成功します。そのため、実際のデータやデータベースが永続的に破損する心配はありません。クエリ内の一部のテーブル(およびそのインデックス)は、頻繁に削除、再作成、および再設定されるため、これに関連していると想定しています。

削除NOLOCKは、私が対処する長期的な問題です。NOLOCKそもそもそこに置かれた理由は、クエリが非常に悪いため、日常のトランザクションでデッドロックが発生しNOLOCK、デッドロックを阻止するためのバンドエイドが機能したためです(機能しました)。ですから、永久的な解決策ができるまで、私はバンドエイドの上にバンドエイドを必要としています。

Hello Worldでそれを再現できれば、おそらく1時間もかからずにバンドエイドを仕事に投入する予定です。検索と置換の削除を実行できませんNOLOCK。これは、アプリのデッドロックが再び発生し始めるためです。

コミットされた読み取りスナップショット分離を使用することは良い可能性です。詳細については、データベースチームと協力する必要があります。私たちの問題の一部は、そのようなことを処理するSQL Serverの専門家がいないことです。また、現時点でその変更を行うのに十分な分離レベルを理解していません。


1
NOLOCKこれらのジョブから単に削除することを検討しましたか?これらのクエリの結果が正確であると想定されている場合は、601があなたの心配の中で最も少ないはずです。ポール・ホワイトは、ここではあり得ないはずのデータの読み取りの特にひどい例を示しています
アーロンバートランド

3
ジョブにを設定DEADLOCK_PRIORITYLOWて、デッドロックが発生した場合に、アプリケーションではなくジョブが失敗するようにすることができます。その後、デッドロックを調査し、それらが発生している理由を見つけ、その問題を修正することができます。2つのステートメントの順序を入れ替えるなど、非常に単純な修正である可能性があります。問題が何であれ、それは解決策NOLOCKないので、それが最も簡単であるという理由だけでそれを強制しようとするのをやめます。
アーロンバートランド

@AaronBertrandありがとう、DEADLOCK_PRIORITYについて知りませんでした-私はそれを調べます。デッドロックの追跡を試みましたが、一見ランダムに見えるさまざまな時間に発生し、1日に1〜2回しか発生せず、オンデマンドで再現することはできません。スケジュールされたジョブは毎時間数万のクエリを実行し、アプリは数百を実行しますページをロードしたり何かを保存したりするたびにクエリの数が増え、デッドロックに関与しているクエリがどちらの側にあるかは追跡していません。私はNOLOCKを永久にそこに残すつもりはありませんでした。そのため、より優れた長期的なソリューションを研究しています。
wookie23

1
あなたはデッドロックを追跡するのに苦労していたと述べました。あなたは2008 R2であることを考えると、あなたはここになります。sqlservercentral.com/articles/deadlock/65658ジョナサンKehayiasはリングバッファからデッドロック情報を引っ張って乗り越えて。
ケネスフィッシャー

回答とコメントは根本的な問題にうまく対処していますが、これを知的演習として再現する方法を見つけることにまだ興味がありますか?
James L

回答:


8

NOLOCK問題への1つの潜在的「バンドエイド」のでNOLOCKを使用して停止し、READ_COMMITTED_SNAPSHOT分離の使用を開始することで、私は、ブログの記事にあなたを指すようにしたいhttp://www.brentozar.comケンドラ・リトルによって:実装スナップショットまたはコミット読取りSQL Serverのスナップショット分離:ガイド

ケンドラは、READ_COMMITTED_SNAPSHOT分離レベルを使用した場合の利点とリスクに関するかなりの詳細を提供します。

  1. この分離レベルは、データベースコードのデフォルトの分離レベルになります。
  2. READ_COMMITTED_SNAPSHOT分離レベルを変更するには、データベースに1人のユーザーのみが必要です。
  3. READ_COMMITTED_SNAPSHOT分離を使用する場合でも、NOLOCKヒントはデフォルトをオーバーライドするため、削除する必要があります。
  4. 一部のコードには、修復が必要な問題がある可能性があります。

数年前、ブロッキングの影響が深刻なデータベースにREAD_COMMITTED_SNAPSHOT分離を実装しました。しかし、分離レベルを変更すると、いくつかの重要な領域でデッドロック発生し始めました。

なぜこれが起こったのですか?以前の分離レベルでは重いブロックが発生したため、コードはデッドロックのポイントに「到達」することはできませんでした。ただし、READ_COMMITTED_SNAPSHOT分離を使用すると、クエリが前進し続ける可能性があります。ただし、待機していないトランザクションの一部がデッドロックを始めました。

幸い、デッドロックポイントを特定し、いくつかのテーブルのインデックスを調整して、より合理的な列の順序にすることで、問題は迅速に解決されました。これにより、ロックの問題が大幅に軽減されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.