У меня есть темпоральная таблица, и я хочу реплицировать ее с помощью репликации транзакций. Таблица истории не может иметь первичный ключ, необходимый для репликации транзакций. Когда я пытаюсь реплицировать текущую таблицу, происходит сбой репликации, поскольку она не может вставить данные в столбцы GENERATED ALWAYS AS ROW START
или GENERATED ALWAYS AS ROW END
.
Как реплицировать темпоральную таблицу
Ответы (3)
Документация Microsoft гласит:
Снимок и репликация транзакций. Поддерживается только для одного издателя без временного включения и одного подписчика с временным включением.
Вот пример темпоральной таблицы с некоторыми фиктивными данными:
CREATE TABLE [dbo].[TemporalTest]
(
[EmployeeID] CHAR(6) NOT NULL,
[EmployeeName] VARCHAR(50) NOT NULL,
[EFF_STRT_TS] DATETIME2(7) GENERATED ALWAYS AS ROW START NOT NULL,
[EFF_END_TS] DATETIME2(7) GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME ([EFF_STRT_TS],[EFF_END_TS]),
CONSTRAINT [PK_TemporalTest] PRIMARY KEY CLUSTERED ([EmployeeID] ASC),
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[TemporalTest_HIST]));
GO
INSERT INTO [dbo].[TemporalTest]
([EmployeeID],[EmployeeName])
VALUES
('000001','Jane Doe'),
('000002','John Smith'),
('000003','John Deer'),
('000004','Dear John')
DELETE FROM [dbo].[TemporalTest]
WHERE [EmployeeID] = '000003'
UPDATE [dbo].[TemporalTest]
SET [EmployeeName] = 'Jane Smith'
WHERE [EmployeeID] = '000001'
Перед репликацией отключите SYSTEM_VERSIONING
.
ALTER TABLE [dbo].[TemporalTest]
SET (SYSTEM_VERSIONING = OFF);
Настройте репликацию транзакций и исключите столбцы периодов [EFF_STRT_TS]
и [EFF_END_TS]
. На реплицированной стороне добавьте столбцы периодов.
ALTER TABLE [dbo].[TemporalTest]
ADD [EFF_STRT_TS] DATETIME2(7) NULL,
[EFF_END_TS] DATETIME2(7) NULL
С помощью служб SSIS скопируйте таблицу истории [TemporalTest_HIST]
с издателя на подписчика. Также с помощью служб SSIS перезапишите текущую таблицу [TemporalTest]
от издателя к подписчику, чтобы значения столбца периода времени точно совпадали и не были нулевыми. После этого измените столбцы на стороне подписчика, чтобы сделать столбцы периода NOT NULL
, и установите их как PERIOD FOR SYSTEM_TIME
.
ALTER TABLE [dbo].[TemporalTest]
ALTER COLUMN [EFF_STRT_TS] DATETIME2(7) NOT NULL
ALTER TABLE [dbo].[TemporalTest]
ALTER COLUMN [EFF_END_TS] DATETIME2(7) NOT NULL
ALTER TABLE [dbo].[TemporalTest]
ADD PERIOD FOR SYSTEM_TIME ([EFF_STRT_TS],[EFF_END_TS])
Как на стороне издателя, так и на стороне подписчика установите SYSTEM_VERSIONING = ON
.
ALTER TABLE [dbo].[TemporalTest]
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[TemporalTest_HIST]));
С этого момента издатель и подписчик будут поддерживать свои собственные темпоральные таблицы с системной версией. Вся структура темпоральной таблицы не реплицируется, поэтому столбцы периодов могут не точно выровняться в зависимости от того, сколько времени занимает репликация.
В моем случае отключения SYSTEM_VERSIONING было недостаточно. Мне также пришлось удалить столбцы perdiod:
ALTER TABLE TemporalTest DROP PERIOD FOR SYSTEM_TIME
Исключение их только в свойствах публикации завершилось следующей ошибкой во время инициализации подписчика.
Сообщение 13504, уровень 16, состояние 1, строка 36. Отсутствует определение временного столбца "ГЕНЕРИРУЕТСЯ ВСЕГДА В НАЧАЛЕ РЯДЫ".
После инициализации вам необходимо добавить столбцы периодов и включить управление версиями системы.
ALTER TABLE [dbo].[TemporalTest]
ADD PERIOD FOR SYSTEM_TIME ([EFF_STRT_TS],[EFF_END_TS])
ALTER TABLE [dbo].[TemporalTest]
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[TemporalTest_HIST]));
Нам нужно было реплицировать только текущую таблицу (в противоположность предполагаемому сценарию Microsoft). Мы создали невременное индексированное представление для «текущей» таблицы и реплицировали индексированное представление. Мы пропустили столбцы системной версии в представлении (не то чтобы я думаю, что это действительно важно).