データウェアハウスに非常に大規模なデータベースがあり、メンテナンスとバックアップを管理するためにパーティションを実装しています。特定の期間のレコードは、最終的には月に1回、読み取り専用ファイルグループに移行されます。
時々、私たちのETLプロセスはすでにアーカイブに移行された古いレコードを更新しようとし、これらが失敗することを予期します。ただし、テスト環境の読み取り専用ファイルグループのパーティションにあるように見えても、テストのレコードが更新される最近の例が少なくとも2つあります(sys.partition_functions
およびsys.partition_range_values
)。
本番環境で同一のレコードを使用すると、レコードを更新しようとしたときに予期される障害が発生します。これまでに2回これをキャッチしましたが、更新は本番環境では失敗しますが、テストでは成功します(その逆はありません)。
関連する環境の事実:
UPDATE 2016-08-19
新しいレコードがどういうわけか一晩で更新されました。読み取り専用ファイルグループ上にあることを確認しました。同時に挿入されたレコードを更新できることがわかりました(つまり、読み取り専用ファイルグループの同じパーティションにもあります)。同じパーティションで単一のレコードを識別し、そのレコードを複数回更新できました。夜間に更新されたレコードを更新しようとすると、予期した障害が発生します。
UPDATE 2016-08-11
更新は、読み取り専用パーティションでのテストの夜間処理中にも発生し続けます。プロセスから同じレコードを更新しようとすると失敗します。以前にそれを更新したユーザーとしてログインしたときに、同じレコードを更新しようとして失敗しました。また、夜間のプロセスでまだ触れられていない同様のレコードを更新して、問題を再現することもできません。
UPDATE 2016-08-04
同じパーティションスキームを使用している別のテーブルで同じ動作の別の発生を発見したため、その単一のテーブルに限定されないことが今日発見されました。
UPDATE 2016-08-03
このMSDNスクリプト からスクリプトを実行すると、Kendra Littleのパーティションヘルパービューph.FilegroupDetail
およびph.ObjectDetail
from このデモ 。問題のレコードはパーティション#2にあります(問題のレコードのパーティション列の値は2015-03-18です)
Filegroup Low Boundary UpperBoundary
Archive (RO) NULL 1900-01-01
Archive (RO) 1900-01-01 2015-04-01
ActiveFG (RW) 2015-04-01 2015-07-01
ActiveFG (RW) 2015-07-01 2015-10-01
ActiveFG (RW) 2015-10-01 2015-01-01
ActiveFG (RW) 2016-01-01 2016-04-01
ActiveFG (RW) 2016-04-01 2016-07-01
ActiveFG (RW) 2016-07-01 2016-10-01
ActiveFG (RW) 2016-10-01 2017-01-01
ActiveFG (RW) 2017-01-01 2115-01-01
ActiveFG (RW) 2115-01-01 NULL
パーティションにテーブルを配置するコード(他のインデックスはありません)
ALTER TABLE [dbo].[TABLE_NAME] ADD CONSTRAINT [pk_TABLE_NAME] PRIMARY KEY CLUSTERED
(
[ETL_VERS_START_DTM] ASC,
[ACCT_NO] ASC,
[ACCT_TYPE] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ps_SmallTablesDate(ETL_VERS_START_DTM)
失敗するはずの更新ステートメント(Informatica経由):
UPDATE TABLE_NAME SET ETL_JOB_SEQ_NUM = ?, ETL_IUD_CD = ?, ETL_UPD_DTM = ?, ETL_DEL_DTM = ? WHERE ETL_VERS_START_DTM = ? AND ACCT_NO = ? AND ACCT_TYPE = ?
ETL_VERS_START_DTM (ETL_VERS_START_DTM:Date:): "03/17/2015 23:30:02.140000000"
ETL_JOB_SEQ_NUM (ETL_JOB_SEQ_NUM:Int:): "1173651"
ETL_IUD_CD (ETL_IUD_CD:Char.1:): "D"
ETL_UPD_DTM (ETL_UPD_DTM:Date:): "08/02/2016 02:32:45.000000000"
ETL_DEL_DTM (ETL_DEL_DTM:Date:): "08/02/2016 00:10:03.567000000"
ACCT_NO (ACCT_NO:Char.12:): "1234567890"
ACCT_TYPE (ACCT_TYPE:Char.3:): "OLN"
UPDATE 2017-02-21
ですから、今回の調査の結果、最も古いアクティブパーティションがアーカイブにマージされたときに、レコードのセクションがディスク上でアクティブファイルグループからアーカイブファイルグループに移動されないことがわかりました。次のクエリは、パーティション2のレコードがActiveFGにマップされていることを示していますが、実際のパーティションスキームを検査すると、それらの同じレコードをパーティション関数によってアーカイブファイルグループにソートする必要があることが示されています。
SELECT OBJECT_NAME(P.[object_id]) ,
P.index_id ,
P.partition_number ,
F.name ,
F.filegroup_guid
FROM sys.allocation_units AU
JOIN sys.partitions P ON P.partition_id = AU.container_id
JOIN sys.filegroups F ON F.data_space_id = AU.data_space_id
WHERE P.partition_number IN ( 1, 2, 3 )
AND P.[object_id] = OBJECT_ID('TABLE_NAME')
ORDER BY P.partition_number;
実際に使用中のデータベースのすべてのパーティションをバックアウトし、Microsoftチケットを処理するために壊れたバージョンのバージョンを保持しました。 DWチームと一緒にパーティション分割計画を修正する必要がありますが、もう一度試すことについては大胆ではありませんが認めます。
マイクロソフトはこの動作を再現することができなかったため、現時点ではチケットを使用しています。彼らはそれをすくめるだけで2014/2016に存在しないと想定する準備ができているように見えますか?私のシステムのバックアップから復元した後でも、データベースに存在し続けることができる私の能力にもかかわらず、彼らは彼らのラボでそれを複製するようには見えません。
私は告白する必要があります。
若い頃、私はETLプロセスを構築しました。まず、読み取り専用ファイルグループを読み取り/書き込みに変更し、そのETL作業を実行してから、それらを読み取り専用に戻しました。
だから、私と同じように悪魔的な同僚がいたら(私は若いので、お金が必要でした)、次の方法でテストできます。
読み取り専用のファイルグループの名前を変更します。そのようにすると、ファイルグループを名前で変更するスクリプトがハードコードされている場合、スクリプトは失敗し、犯人を捕まえます。または、少し難しい:
プロファイラーまたは拡張イベントを使用して、ALTER DATABASEを実行するすべてのユーザーを追跡します。