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

Откуда:
Сообщений: 5
В базе существуют две таблицы, каждая имеет поле типа timestamp. В первую таблицу добавляются пользователи, во второй хранятся их телефонные номера.
Задача - в промежуточную базу выгружать связки "абонент - телефон". Помятуя о том, что поле типа timestamp изменяется в момент коммита(не могу найти, где я это вычитал), возникла прекрасная, как тогда казалось, идея - каждый раз при запуске процедуры выгрузки в промежуточную базу запоминать максимальный timestamp из этих двух таблиц, сохранять его в промежуточной базе, а при следующем вызове процедуры его считывать, и обрабатывать только те записи, timestamp которых будет лежать в интервале между предыдущим и текущим максимуме.
Все это прекрасно работало, пока выгрузка осуществлялась раз в сутки, глубокой ночью. Когда же возникла необходимость выгружать связки раз в час, выяснилось, что в основной базе стали появляться связки, не выгруженные в промежуточную.
Поэтому возник вопрос к уважаемому сообществу - не ошибался ли я, полагая, что timestamp обновляется в момент коммита? Потому как я не вижу другого объяснения происходящего, кроме того, что очередное значение timestamp для добавляемой записи в любую из двух таблиц резервируется в момент начала транзакции, а при коммите только фиксируется, и тогда, если транзакция началась до момента запуска процедуры выгрузки, и завершилась уже после ее окончания, то ее timestamp окажется внутри уже отработанного интервала?
То есть, если кратко - возможна ли ситуация, когда из нескольких транзакций, начатых параллельно, транзакция, завершившаяся последней, будет иметь timestamp меньший, чем транзакция, завершившаяся раньше?
10 янв 17, 13:32    [20088790]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
invm
Member

Откуда: Москва
Сообщений: 9396
Taras1975
Помятуя о том, что поле типа timestamp изменяется в момент коммита
https://msdn.microsoft.com/en-us/library/ms182776.aspx
Each database has a counter that is incremented for each insert or update operation that is performed on a table that contains a rowversion column within the database.
10 янв 17, 13:54    [20088939]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Taras1975
Member

Откуда:
Сообщений: 5
Не могли бы вы ответить более развернуто? Мне следовало вместо "изменяется" написать "инкрементируется"?
10 янв 17, 14:17    [20089110]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10234
Блог
ошибочно ваше мнение, что "timestamp изменяется в момент коммита"
10 янв 17, 14:19    [20089134]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10234
Блог
а по сути вашей проблемы - запоминайте последний min_active_rowversion() и от него пляшите
10 янв 17, 14:27    [20089214]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Ролг Хупин
Member

Откуда: Чебаркуль
Сообщений: 3739
Taras1975
Не могли бы вы ответить более развернуто? Мне следовало вместо "изменяется" написать "инкрементируется"?


Пишут такое:
"The rowversion(timestamp) starts changing as soon as the transaction begins. If the transaction is rolled back, it returns to the original value. "

и учитывая то, что "параллельно" стартующие транзакции стратуют реально в разное время, то у вас всё логично.
10 янв 17, 14:28    [20089220]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4804
Taras1975,

Я много поработал с timestamp.
Ваша ошибка здесь

"
каждый раз при запуске процедуры выгрузки в промежуточную базу запоминать максимальный timestamp из этих двух таблиц, сохранять его в промежуточной базе, а при следующем вызове процедуры его считывать, и обрабатывать только те записи, timestamp которых будет лежать в интервале между предыдущим и текущим максимуме.
"


Вам нужно внимательно изучить функцию MIN_ACTIVE_ROWVERSION()

https://msdn.microsoft.com/en-us/library/bb839514.aspx

Выгружать надо от максимальной ранее загруженной до MIN_ACTIVE_ROWVERSION() иначе вы будет пропускать еще не закоммиченные записи, как раз выглядит как вы описали.
10 янв 17, 14:30    [20089240]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
aleks2
Guest
Knyazev Alexey
ошибочно ваше мнение, что "timestamp изменяется в момент коммита"

С этого места подробнее!
10 янв 17, 14:56    [20089439]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Taras1975
Member

Откуда:
Сообщений: 5
Knyazev Alexey, Ролг Хупин - спасибо за помощь!
a_voronin - отдельное большое спасибо за исчерпывающий ответ!
10 янв 17, 15:07    [20089550]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10234
Блог
aleks2
Knyazev Alexey
ошибочно ваше мнение, что "timestamp изменяется в момент коммита"

С этого места подробнее!


вот кому уж точно я ничего объяснять не буду, так это вам...ваш быдлоформат общения уже многим на форуме надоел...
10 янв 17, 15:10    [20089573]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 5975
aleks2
Knyazev Alexey
ошибочно ваше мнение, что "timestamp изменяется в момент коммита"

С этого места подробнее!

А что не так?
if object_id('tempdb..#t') is not null
  drop table #t;
create table #t (
  id int not null,
  rv rowversion
);
go
insert into #t(id) values(1)
go
declare
  @s varchar(16), @n int;
select @s=convert(varchar, convert(binary(8), rv), 2) from #t;
raiserror(@s, 0, 0) with nowait;
begin tran;
update #t set id=id+1;
select @s=convert(varchar, convert(binary(8), rv), 2) from #t;
raiserror(@s, 0, 0) with nowait;
select @n=1 waitfor delay '00:00:05';
commit;
select @s=convert(varchar, convert(binary(8), rv), 2) from #t;
raiserror(@s, 0, 0) with nowait;

Вывод:

0000000002013E6B

(1 row(s) affected)
0000000002013E6C
0000000002013E6C
10 янв 17, 15:13    [20089596]     Ответить | Цитировать Сообщить модератору
 Re: неожиданное поведение timestamp  [new]
aleks2
Guest
Сон Веры Павловны
aleks2
пропущено...

С этого места подробнее!

А что не так?
if object_id('tempdb..#t') is not null
  drop table #t;
create table #t (
  id int not null,
  rv rowversion
);
go
insert into #t(id) values(1)
go
declare
  @s varchar(16), @n int;
select @s=convert(varchar, convert(binary(8), rv), 2) from #t;
raiserror(@s, 0, 0) with nowait;
begin tran;
update #t set id=id+1;
select @s=convert(varchar, convert(binary(8), rv), 2) from #t;
raiserror(@s, 0, 0) with nowait;
select @n=1 waitfor delay '00:00:05';
commit;
select @s=convert(varchar, convert(binary(8), rv), 2) from #t;
raiserror(@s, 0, 0) with nowait;

Вывод:

0000000002013E6B

(1 row(s) affected)
0000000002013E6C
0000000002013E6C


До "момента коммита" - фсе это "недоступно" при нормальной работе.
А то можно договориться, что любое значение, задаваемое в UPDATE, "меняется сразу".
11 янв 17, 09:57    [20092380]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить