データウェアハウスに非常に大規模なデータベースがあり、メンテナンスとバックアップを管理するためにパーティションを実装しています。特定の期間のレコードは、最終的には月に1回、読み取り専用ファイルグループに移行されます。
時々、私たちのETLプロセスはすでにアーカイブに移行された古いレコードを更新しようとしますが、これらは失敗すると予想されます。ただし、テスト環境のレコードが読み取り専用ファイルグループのパーティションにあるように見える場合でも、テストのレコードが更新される最近の例が少なくとも2つあります(クエリsys.partition_functions
とsys.partition_range_values
)。
本番環境で同一のレコードを使用すると、レコードを更新しようとしたときに予期したエラーが発生します。これまでに2回これをキャッチしましたが、更新は本番環境では失敗しますが、テストでは成功します(その逆はありません)。
関連する環境の事実:
- SQL Server 2012 SP3 CU3(ビルド11.0.6537.0)
- テストは開発者版、製品はエンタープライズ版
- リクエストに応じて他のユーザーに提供できます:現在深刻な困惑しています...
更新2016-08-19
新しいレコードがどういうわけか一晩で更新されました。読み取り専用ファイルグループ上にあることを確認しました。同時に挿入された(つまり、読み取り専用ファイルグループの同じパーティションにもある)レコードを更新できることがわかりました。同じパーティションで単一のレコードを識別し、そのレコードを複数回更新できました。夜間に更新されたレコードを更新しようとすると、予期した障害が発生します。
更新2016-08-11
更新は、読み取り専用パーティションでのテストの夜間処理中にも発生し続けます。プロセスから同じレコードを更新しようとすると失敗します。以前にそれを更新したユーザーとしてログインしたときに、同じレコードを更新しようとして失敗しました。私はまた、毎晩のプロセスでまだ触れられていない同様のレコードを更新して問題を再現することはできません。
更新2016-08-04
同じパーティションスキームを使用して、別のテーブルで同じ動作の別の発生を発見したため、その単一のテーブルに限定されないことを今日発見しました。
更新2016-08-03
このMSDNスクリプトからスクリプトを実行すると、Kendra Littleのパーティションヘルパービューを使用したときに得られる結果ph.FilegroupDetail
とph.ObjectDetail
、このデモから確認できます。問題のレコードはパーティション#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"
更新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に存在しないと想定する準備ができているように見えますか?私のシステムのバックアップから復元した後でも、データベースに存在し続けることができる私の能力にもかかわらず、彼らは彼らのラボでそれを複製するようには見えません。