web-dev-qa-db-ja.com

クラスター化インデックスの再編成時にセカンダリからデータを読み取る際の問題

SQL Server 2014 SP2 CU5(3ノード)にAOAGがあります。 Read Committed Snapshot Isolationレベル[〜#〜] on [〜#〜]。大きなテーブルが圧縮されています。このテーブルに対するいくつかの大きなクエリは、セカンダリに実行されます。

次に、プライマリノードに夜間ジョブがあり、いくつかのテーブルのインデックスを再編成します。上記のテーブルのクラスター化インデックスにヒットすると、次のエラーが発生します。

データベース「yyyy」のテーブル「xxxx」のバージョン対応行にアクセスすると、トランザクションが中止されました。バージョンを作成しようとした操作に対して読み取り可能なセカンダリアクセスが許可されていないため、要求されたバージョン対応行が見つかりませんでした。

ある時点で、大きなクエリはヒントREADUNCOMMITTEDで読み取りを実行していました。それが原因だと思ったので削除しました。しかし、エラーはまだそこにあります。

何か案は?

現在の設定:

  • 02セカンダリは同期モードです
  • 03非同期モードのセカンダリ

AOAG current setup

テーブルの詳細

  • RowCounts:122.567.668
  • TotalSpaceMB:18.460
  • UsedSpaceMB:18.238

定義:

CREATE TABLE [dbo].[big_table](
[ID] [int] NOT NULL IDENTITY(1, 1),
1 [int] NULL,
2 [datetime] NULL,
3 [int] NULL,
4 [int] NULL CONSTRAINT [DF_ccc_bUnits] DEFAULT ((0)),
5 [money] NULL,
6 [money] NULL,
7 [int] NULL,
8 [int] NULL CONSTRAINT [DF_ccc_MinDays] DEFAULT ((0)),
9 [int] NULL,
10 [int] NULL,
11 [float] NULL,
12 [money] NULL,
13 [int] NULL,
14 [int] NULL,
15 [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
16 [money] NULL,
17 [money] NULL,
18 [int] NULL,
19 [int] NULL,
20 [money] NULL,
21 [money] NULL,
22 [money] NULL,
23 [money] NULL,
24 [money] NULL,
25 [datetime] NOT NULL CONSTRAINT [DFcccadded] DEFAULT (getdate()),
26 [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
27 [money] NOT NULL CONSTRAINT [DFcccBrf] DEFAULT ((0)),
29 [money] NOT NULL CONSTRAINT [DFcccHB] DEFAULT ((0)),
30 [money] NOT NULL CONSTRAINT [DFcccFB] DEFAULT ((0)),
31 [money] NOT NULL CONSTRAINT [DFcccAllBoards] DEFAULT ((0)),
32 [money] NOT NULL CONSTRAINT [DFcccChildBrf] DEFAULT ((0)),
33 [money] NOT NULL CONSTRAINT [DFcccChildHB] DEFAULT ((0)),
34 [money] NOT NULL CONSTRAINT [DFcccChildFB] DEFAULT ((0)),
35 [money] NOT NULL CONSTRAINT [DFcccChildAllBoards] DEFAULT ((0)),
36 [int] NULL CONSTRAINT [DFcccShow_1] DEFAULT ((0)),
37 [timestamp] NOT NULL,
38 [money] NULL,
39 [money] NULL,
40 [money] NULL,
41 [money] NULL,
42 [money] NULL,
43 [money] NULL,
44 [money] NULL,
45 [money] NULL,
46 [int] NOT NULL CONSTRAINT [DFcccReleaseHour] DEFAULT ((0)),
47 [int] NULL,
48 [int] NULL,
49 [money] NULL,
50 [money] NULL,
51 [float] NULL
) ON [PRIMARY]
WITH (DATA_COMPRESSION = PAGE)
GO
CREATE UNIQUE CLUSTERED INDEX [IXccc] ON [dbo].[big_table] (1, 2) WITH (FILLFACTOR=90, DATA_COMPRESSION = PAGE) ON [PRIMARY]
GO
ALTER TABLE [dbo].[big_table] ADD CONSTRAINT [PKccc] PRIMARY KEY NONCLUSTERED ([ID]) WITH (DATA_COMPRESSION = PAGE) ON [secondary]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IXcccstamp] ON [dbo].[big_table] (36) INCLUDE (1, 2) WITH (FILLFACTOR=100) ON [PRIMARY]
GO
7
Yaroslav

そのため、考えられる解決策を使い果たした後、マイクロソフトにサポートケースをオープンしました。彼らは、プロセスの実行中にいくつかの情報を収集するツールを実行するように依頼し、その後それを分析しました。ここに彼らの答えがあります:

  • インデックスの再編成ジョブが開始される前に開始した場合、selectコマンドは正常に実行されています
  • 再編成ジョブの開始後に選択コマンドを開始すると、選択コマンドが失敗します。
  • 上記の動作はAGで予想される動作であることがわかりました。
    • 行のバージョン管理のため、読み取り操作は共有ロックを取得しませんが、これらの操作はスキーマ安定性(Sch-S)ロックを取得するため、DDL変更を適用しているREDO操作をブロックできます。 DDL操作には、ALTER/DROPテーブルとビューが含まれますが、ストアドプロシージャのDROPまたはALTERは含まれません。
    • 私たちのケースでは、インデックスの再編成がプライマリREDO操作で実行されているときに、セカンダリレプリカで実行され、Sch-M(スキーマ変更ロック)を取得しています。selectコマンドが同じレプリカにアクセスしようとすると、同じレプリカにアクセスできません。 Sch-Mロックを持っているREDOスレッドによってすでに占有されているため、Sch-S(スキーマ安定性)ロックを取得します。
    • このシナリオでは、アプリケーションがタイムアウトエラーを含むエラーを生成しています。
  • この種の状況を回避するには、インデックスの再編成タスクを営業時間外にスケジュールすることをお勧めします

「営業時間外」はありません。24時間年中無休で営業しています。決定的な答えではありませんが、少なくともこの問題の根本的な原因はわかっています。したがって、アプローチは一時的に接続文字列を変更することです。これにより、失敗したタスクは、インデックスの再作成の実行時にセカンダリAGノードではなくプライマリAGノードから読み取られます。

0
Yaroslav