Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Узнать какая из параллельных транзакций была последней без использования rowversion / 20 сообщений из 20, страница 1 из 1
25.01.2020, 04:20
    #39918612
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Предположим, строку таблицы многопоточно изменяет множество хранимых процедур.

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

Вопрос: как мне узнать, какое из возвр. значений будет новейшим(последним) в коллекции?

Если добавить rowversion то соотв. включится счетчик обновлений, который можно вернуть с возвращаемым значением и тем самым определить последнее изменение данных, но хотелось бы решение без создания доп колонки.

Я было подумал, что @@DBTS инкрементится при каждом обновлении базы, но нет - только при добавлении rowversion в соотв таблицу.

Может есть какой еще счетчик? Я так понимаю, что всякие transaction_id transaction_sequence_num мне тут не помогут..

Спасиб...
...
Рейтинг: 0 / 0
25.01.2020, 09:19
    #39918621
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon
Каждая процедура имеет возможность узнать конечный результат своих действий над данными(свою последнюю версию данных) и вернуть его вызывающей стороне(коллеру) образуя коллекцию.

Вопрос: как мне узнать, какое из возвр. значений будет новейшим(последним) в коллекции?
Если "Каждая процедура имеет возможность узнать конечный результат своих действий", то этот результат и является последним.

Узнать это можно, используя "output" в командах изменений.
...
Рейтинг: 0 / 0
25.01.2020, 10:19
    #39918625
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon
Может есть какой еще счетчик?
Код: sql
1.
2.
3.
4.
5.
select
 dt.database_transaction_last_lsn
from
 sys.dm_tran_current_transaction ct join
 sys.dm_tran_database_transactions dt on dt.transaction_id = ct.transaction_id and dt.database_id = db_id();
...
Рейтинг: 0 / 0
25.01.2020, 13:48
    #39918654
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
alexeyvg
peon
Каждая процедура имеет возможность узнать конечный результат своих действий над данными(свою последнюю версию данных) и вернуть его вызывающей стороне(коллеру) образуя коллекцию.

Вопрос: как мне узнать, какое из возвр. значений будет новейшим(последним) в коллекции?
Если "Каждая процедура имеет возможность узнать конечный результат своих действий", то этот результат и является последним.

Узнать это можно, используя "output" в командах изменений.


В контексте самой процедуры естественно ее результат будет последним, но в в контексте пула одновременно выполняемых процедур нет. Мне это все нужно, чтобы возвращаемые данные одновременно застряли в моем кэше, ну и версия(через перезаписывания) этих данных была бы последней(относительно несуществующего rowversion). Если бы база инкрементила @@DBTS при каждом обновлении любой строки я бы мог просто использовать этот счетчик для упорядочивания версий данных.
...
Рейтинг: 0 / 0
25.01.2020, 13:52
    #39918660
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
invm
peon
Может есть какой еще счетчик?
Код: sql
1.
2.
3.
4.
5.
select
 dt.database_transaction_last_lsn
from
 sys.dm_tran_current_transaction ct join
 sys.dm_tran_database_transactions dt on dt.transaction_id = ct.transaction_id and dt.database_id = db_id();



Ой как все сложно. :) Я так и подумал, что единственный вариант - это через место транзакции в логе..
...
Рейтинг: 0 / 0
25.01.2020, 13:57
    #39918661
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
@@DBTS возвращает последний сгенерированный rowversion для базы, а не для конкретной сессии. И между модификацией данных в вашей сессии и получением значения переменной, запросто может произойти еще одна модификация, и в вашей сессии вы получите уж не свой, а чужой rowversion.

На lsn я бы тоже не стал закладываться. Плохо использовать физические инструменты, которые от версии к версии могут меняться, для решения логической задачи.
...
Рейтинг: 0 / 0
25.01.2020, 14:04
    #39918663
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon,

причем здесь пул? Значит он у Вас неверно организован. Выполнение процедур атомарно в рамках транзакции. Т.е. каждая процедура совершенно точно "знает", что она сделала и может вернуть результат пулу. Извлечь данные, которые обработала процедура, можно введение кода в процедуру с выражением запроса output, как писали об этом.
...
Рейтинг: 0 / 0
25.01.2020, 14:45
    #39918680
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Гавриленко Сергей Алексеевич
На lsn я бы тоже не стал закладываться. Плохо использовать физические инструменты, которые от версии к версии могут меняться, для решения логической задачи.


А что делать - иначе задачу не решить.
Кстати на lsn(логе) работают многие продвинутые инструменты( https://debezium.io/ )

...

У меня могут быть сотни одновременных писателей в счетчик и как мне уведомлять "старых" клиентов о том, что их данные со счетчика устарели - не заставлять же их поллить базу - только через пуш в них новой версии - а это уже кеширование(версионность) на уровне приложения, но в кеше то должна всегда находится последнее обновление счетчика, соотв. запись в кэш происходит через условие, такое как rowversion или вот тот же LSN - надеюсь он доступен из контекста хранимой процедуры или сразу после нее, уникально характеризуя оставленный в базе след и его версию.
...
Рейтинг: 0 / 0
25.01.2020, 14:50
    #39918682
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Гавриленко Сергей Алексеевич
@@DBTS возвращает последний сгенерированный rowversion для базы, а не для конкретной сессии.


Да, вот если бы каждый поток сохранял @@DBTS в собственный счетчик(эдакий rowversion, но в рамках всей базы а не отдельной строки и в рамках каждого потока)... ну и инкрементится @@DBTS только для строк с rowversion
https://docs.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact-sql?view=sql-server-ver15
...
Рейтинг: 0 / 0
25.01.2020, 14:58
    #39918684
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon,

авторкак мне уведомлять "старых" клиентов о том, что их данные со счетчика устарели
это же другая задача, не та, что описана в начале.
Задача информирования клиентского приложения об изменениях в базе можно реализовать, например, как в статье https://github.com/dyatchenko/ServiceBrokerListener .
...
Рейтинг: 0 / 0
25.01.2020, 15:55
    #39918696
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon
Гавриленко Сергей Алексеевич
@@DBTS возвращает последний сгенерированный rowversion для базы, а не для конкретной сессии.


Да, вот если бы каждый поток сохранял @@DBTS в собственный счетчик(эдакий rowversion, но в рамках всей базы а не отдельной строки и в рамках каждого потока)... ну и инкрементится @@DBTS только для строк с rowversion
https://docs.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact-sql?view=sql-server-ver15
То он бы сразу стал не нужен в ситуации, когда за раз меняется более одной строки.
...
Рейтинг: 0 / 0
25.01.2020, 16:44
    #39918701
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Гавриленко Сергей Алексеевич,

логично, надо же сериализовать в рамках потока изменений даже в контексте одной транзакции, т.е. буквально каждое обновление строки соотносить с уникальным значением счетчика.. ох, тогда и lsn отлетает, т.к. он характеризует совокупность изменений за одну транзакцию
...
Рейтинг: 0 / 0
25.01.2020, 16:48
    #39918703
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Владислав Колосов,

мне кажется https://github.com/dyatchenko/ServiceBrokerListener в итоге будет гораздо медленнее решения на rowversion
...
Рейтинг: 0 / 0
25.01.2020, 17:55
    #39918711
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon
тогда и lsn отлетает, т.к. он характеризует совокупность изменений за одну транзакцию
Откуда такие фантазии?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
use tempdb;
go

create table dbo.t (id int primary key, v int);
insert into dbo.t values (1, 1);
go

begin tran;

update dbo.t set v += 1 where id = 1;

select
 dt.database_transaction_last_lsn
from
 sys.dm_tran_current_transaction ct join
 sys.dm_tran_database_transactions dt on dt.transaction_id = ct.transaction_id and dt.database_id = db_id();

update dbo.t set v += 1 where id = 1;

select
 dt.database_transaction_last_lsn
from
 sys.dm_tran_current_transaction ct join
 sys.dm_tran_database_transactions dt on dt.transaction_id = ct.transaction_id and dt.database_id = db_id();
rollback;
go

drop table dbo.t;
go
...
Рейтинг: 0 / 0
25.01.2020, 23:39
    #39918736
Gerros
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon
У меня могут быть сотни одновременных писателей в счетчик и как мне уведомлять "старых" клиентов о том, что их данные со счетчика устарели
А зачем этим писателям знать что счётчик устарел?

Вы собираетесь сделать кэш, который будет отправлять уведомления клиентам об изменении счётчика.
А почему бы не сделать так, чтобы клиент получать значение счётчика не запуском хранимки, а через этот ваш кэш? А уже кэш будет выстраивать клиентские запросы в очередь, работать с базой и уведомлять клиентов.

А вообще, можете сформулировать задачу как она есть, а не как вы собрались её решать?
...
Рейтинг: 0 / 0
26.01.2020, 13:40
    #39918797
peon
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Gerros,

Так кэш же сам должен быть в актуальном состоянии(содержать последние изменения счетчиков).

...

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

При первом изменении счетчика регистрировать клиента(терминал) через создание соотв. таблицы при дальнейших изменениях счетчика со стороны первого клиента и последующих дополнять таблицу идентификаторами новых клиентов(подписчиков на изменение данных). Ну и по таймеру периодически бегать по такой таблице и обновлять счетчики у клиентов через пуш(если клиент отвалился и не отреагировал на пуш сотв. удалять его ID из таблицы подписчиков на соотв счетчик).

Т.е. обновление устаревших версий данных счетчиков на терминалах клиентов делать асинхронным.
...
Рейтинг: 0 / 0
27.01.2020, 12:44
    #39919041
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon,

Пробейте свои возвращаемые значение ROW_NUMBER, если там нет IDENTITY и успокойтесь. И что в вашем понимании последнее? Последняя запись по номеру, последняя по некоей дате? Вы кинули в таблицу 10 записей, если у них нет сортирующего ключа, то понятия "первое" "предыдущее" "последнее" тут отсутствует.
...
Рейтинг: 0 / 0
27.01.2020, 12:48
    #39919046
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon,

Для лиц понимающих толк в извращениях

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
use tempdb
go
CREATE TABLE T(X INT);

INSERT INTO T VALUES(1),(2)

SELECT %%physloc%% AS [%%physloc%%],
       sys.fn_PhysLocFormatter(%%physloc%%) AS [File:Page:Slot]
FROM T
...
Рейтинг: 0 / 0
27.01.2020, 13:12
    #39919057
Exproment
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
peon
Предположим, строку таблицы многопоточно изменяет множество хранимых процедур.

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

Вопрос: как мне узнать, какое из возвр. значений будет новейшим(последним) в коллекции?

Версионность в разрезе каждой строки ? Вам не нужен rowversion. Добавлете поле inc_version и делаете его +1 каждый апдейтом, через output получаете результат и возвращаете клиенту.

Если нужно глобально, то:
  • можете сразу после апдейта делать +1 через сиквенс, возвращая результат клиенту. Но надо протестить под нагрузкой, может не прокатит.
  • создаете таблицу логов с монотонно возрастающим ключен, который получаете из неё - 100% рабочий вариант.
...
Рейтинг: 0 / 0
27.01.2020, 13:38
    #39919070
Exproment
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Узнать какая из параллельных транзакций была последней без использования rowversion
Exproment
можете сразу после апдейта делать +1 через сиквенс, возвращая результат клиенту. Но надо протестить под нагрузкой, может не прокатит.

В общем тут надо просто транзакцию закрывать после next value for, чтобы гарантировать что никто не вклинится между апдейтом записи и операцией +1. Вот так у вас будут версии, без изменения структуры таблиц:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
begin tran

	update my_table
	set		my_data = 'the most ne data'
	where	my_key = 1 

	select next value for dbo.seq_version

commit
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Узнать какая из параллельных транзакций была последней без использования rowversion / 20 сообщений из 20, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]