Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Change Tracking: Объясните, как такое получается.  [new]
ShIgor
Member

Откуда: Нижний Новгород
Сообщений: 2192
Имеем, sql2014 express, база 1С, на одной таблице настроен CT без отслеживания изменений по полям.
Все работает, все хорошо в 99.99% случаев.
Но иногда возникает такая ситуация: при запросе из
select ct.sys_change_version, ct.sys_change_operation, ct._IDRRef, sct.commit_ts, sct.xdes_id, sct.commit_time
from 
  changetable(changes _DocumentXXX, 456236) ct
  inner join sys.dm_tran_commit_table sct on ct.sys_change_version = sct.commit_ts

получаю 2 записи:
sys_change_versionsys_change_operation_IDRRefcommit_tsxdes_idcommit_time
456237U0x828494C6911BAE8E11E889E85F56DDB845623735667992018-07-17 17:46:05.683
456237U0x828494C6911BAE8E11E889E85F56DDB845623735668002018-07-17 17:46:05.683


отличаются они только полем xdes_id
достучаться до конкретных изменений можно только через DAC, поэтому для решения уж никак не подходит.
Но смотрим, что произошло:
select * from sys.change_tracking_539148966 where sys_change_xdes_id between 3566799 and 3566800

sys_change_xdes_idsys_change_xdes_id_seqsys_change_operationk__IDRRef_00000001
356679928375U0x828494C6911BAE8E11E889E91273AB1B
356680028376U0x828494C6911BAE8E11E889E85F56DDB8


и видим что xdes_id = 3566799 не может иметь никакого отношения к commit_ts = 456237, т.к. PK разные!!!
да и
select ct.sys_change_version, ct._IDRRef from changetable(version _Document126, (_IDRRef), (0x828494C6911BAE8E11E889E91273AB1B)) ct

sys_change_version_IDRRef
4562910x828494C6911BAE8E11E889E91273AB1B

совсем другая...

Как так???

от MS кроме https://support.microsoft.com/en-us/help/3083381/duplicate-key-rows-from-the-sys-syscommittab-table-in-sql-server
ничего не нашел, но оно вроде к моей проблеме отношения не имеет.
18 июл 18, 18:51    [21582285]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
ShIgor
Member

Откуда: Нижний Новгород
Сообщений: 2192
ShIgor,

Ну разобрался вроде, поэтому сам себе и отвечу.

Итак, подобие первого запроса широко распространено в примерах в сети и даже в книгах. Цель этого запроса - получить расширенную информацию о прошедшем изменении. В частности - нужно было получить время когда в действительности произошел коммит (commit_time).

Дальше нам нужно понять что-же такое commit_ts (оно же sys_change_version) и xdes_id.
это поля из sys.dm_tran_commit_table
грубо:
xdes_id - внутр идентификатор для транзакции
commit_ts - последовательный номер коммита для транзакции (CSN Commit Sequence Number)

есть еще commit_csn - это тоже самое что и commit_ts, только нумерация instance-wide (на моих данных значения разные, а поведение одинаковое и дальше рассматривать его не буду)

из вышесказанного получается, что в один коммит могут влезть несколько разных транзакций и совсем необязательно от одной таблицы на которых настроен CT.

Другая часть запроса это функция CHANGETABLE с параметром changes - возвращает список записей (PK) для которых были изменения и (важно) последняя операция и последний номер коммита для каждой измененной записи.

Ну а дальше понятно - связав обе сущности можно получить умножение записей. CHANGETABLE не обращает внимание на то, что в одном коммите могут оказаться несколько транзакций и для каждого измененного PK он вернет один и тот же commit_ts. Самый худший вариант в этом случае декартово произведение.

Переводя на мою ситуацию, если бы commit_ts был бы последний на момент запроса, я получил бы ответ:
sys_change_versionsys_change_operation_IDRRefcommit_tsxdes_idcommit_time
456237U0x828494C6911BAE8E11E889E85F56DDB845623735667992018-07-17 17:46:05.683
456237U0x828494C6911BAE8E11E889E85F56DDB845623735668002018-07-17 17:46:05.683
456237U0x828494C6911BAE8E11E889E91273AB1B45623735667992018-07-17 17:46:05.683
456237U0x828494C6911BAE8E11E889E91273AB1B45623735668002018-07-17 17:46:05.683


Самое печальное, что без DAC корректную связь между ними получить невозможно.

кстати, вот один из примеров с этой засадой:
http://yabele.blogspot.com/2015/07/mssql-change-tracking-how-can-i-get.html
19 июл 18, 14:39    [21585239]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 6536
ShIgor,

судя по справке, это - временнАя метка каждой транзакции (номер версии).

автор
все хорошо в 99.99% случаев

Хорошо для чего?
20 июл 18, 01:52    [21586901]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
ShIgor
Member

Откуда: Нижний Новгород
Сообщений: 2192
Владислав Колосов,

хорошо - в смысле все работает, и отслеживается как надо.
но этот метод получения commit_time приводит к дублированию записей и, соответственно, к дополнительной последующей обработке, нагрузке и т.п.
20 июл 18, 09:30    [21587269]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 6536
ShIgor,

хм, я полагал, что информации о версии, которую возвращает changetable() и CHANGE_TRACKING_CURRENT_VERSION() достаточно для инкрементного запроса при синхронизации данных.
23 июл 18, 17:07    [21595002]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
ShIgor
Member

Откуда: Нижний Новгород
Сообщений: 2192
Владислав Колосов,

ну, СТ используется не только для синхронизации.
для аудита, например, этих данных недостаточно.
23 июл 18, 18:57    [21595372]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 6536
ShIgor,

я намекаю на то, что вы используете инструмент не по его назначению, а потом жалуетесь ;)
24 июл 18, 13:34    [21597900]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
ShIgor
Member

Откуда: Нижний Новгород
Сообщений: 2192
Владислав Колосов,

странные умозаключения.
24 июл 18, 15:25    [21598491]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
ДонАтелло
Member

Откуда:
Сообщений: 24
ShIgor
грубо:
xdes_id - внутр идентификатор для транзакции
commit_ts - последовательный номер коммита для транзакции (CSN Commit Sequence Number)

из вышесказанного получается, что в один коммит могут влезть несколько разных транзакций и совсем необязательно от одной таблицы на которых настроен CT.


Не очень понятно как Вы пришли к такому выводу. Точнее кажется, что Вы пришли к такому выводу исключительно из определений этих двух полей. На самом деле, Вы, просто, констатируете факт того, что в sys.dm_tran_commit_table, каким то чудом оказалось две записи с одним commit_ts. Ибо в каком-либо другом контексте фраза "...в один коммит могут влезть несколько разных транзакций" звучит пугающе.

ShIgor
Ну а дальше понятно - связав обе сущности можно получить умножение записей. CHANGETABLE не обращает внимание на то, что в одном коммите могут оказаться несколько транзакций и для каждого измененного PK он вернет один и тот же commit_ts.


Немного некорректно. У Вас две таблицы в запросе и Вы соединяете их. Первая - changetable(...) работает честно и возвращает одну запись. Она не обязана ничего знать о второй таблице sys.dm_tran_commit_table в которой данные уже задвоены к моменту выполнения.

ShIgor
Переводя на мою ситуацию, если бы commit_ts был бы последний на момент запроса, я получил бы ответ:


Тоже непонятно. При чём тут последний коммит или нет?

Что касается конкретно Вашей ситуации, то было опрометчиво писать такой запрос, не зная ключей в таблице sys.syscommittab (это подложенная под представление sys.dm_tran_commit_table таблица). Если не знаете ключей - то нужно перестраховываться чем-то типа

В целом - тема интересная
5 июл 19, 17:54    [21921774]     Ответить | Цитировать Сообщить модератору
 Re: Change Tracking: Объясните, как такое получается.  [new]
ДонАтелло
Member

Откуда:
Сообщений: 24
Прошу прощения. Нечаянно отправил недописанное сообщение. Продолжу:

Что касается конкретно Вашей ситуации, то было опрометчиво писать такой запрос, не зная ключей в таблице sys.syscommittab (это подложенная под представление sys.dm_tran_commit_table таблица). Если не знаете ключей - то нужно перестраховываться чем-то типа
cross apply (select top 1 * from sys.dm_tran_commit_table sct where sct.commit_ts = ct.sys_change_version)


В целом - случай интересный. Если у кого-то есть возможность воспроизвести то же самое поведение, то интересно было бы глянуть на результат запроса
select top 1 from sys.dm_tran_commit_table sct where sct.xdes_id in (3566799, 3566800)


Т.е. исследовать откуда же появились две транзакции с одним commit_ts.

Я работаю над универсально обёрткой вокруг CT или CDC. Связано это с тем, что CDC доступен не на всех редакциях SQL. С CDC всё достаточно просто, там LSN и SeqNO из журнала транзакций. Оба numeric(25). В CT же Майкрософт ввёл новые характеристики, обозначающие версию данных sys_change_version тот же самый... bigint. А Sequance вообще спрятали, через функции её не достать, только в таблицах из под DAC.
Т.е. мне интересно внутреннее устройство CT и хотелось бы доковырять этот пример для лучшего понимания внутренностей и засад.
Спасибо.
5 июл 19, 18:06    [21921779]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить