SQL Server и PRAM consistency

agaaaa

Рассмотрим сценарий:
Клиент 1:
Транзакция 1
Select + Update над таблицей 1
Конец транзакции 1
Работаем с таблицей 2 без транзакций (опер Х)
Транзакция 2
Select and update над таблицей 1
Конец транзакции 2
Вопрос: Гарантируется ли, что Клиент 2, прочитавший из таблицы 1 результат транзакции 2 , после этого прочитает таблицу 2 в её конечном виде (операция Х завершилась).
Операция Х, скорее всего, будет сложной.
П.С. Где про это почитать подробнее.

hprt

Почитай про уровни изоляции транзакций. http://msdn.microsoft.com/en-us/library/ms173763.aspx

agaaaa

Статья по ссылке не имеет отношения к поставленному вопросу.
Погуглил ещё. Нашёл вот это:
http://technet.microsoft.com/en-us/library/ms174377.aspx
Если я правильно понял, то каждый оператор в работе над таблицей 2 является независимой транзакцией. Но мне всё равно не понятно, гарантируется ли для другого клиента, что работа над таблицей 2 обязана выглядеть завершённой после прочтения этим клиентом таблицы 1 в состоянии после транзакции 2.

katrin2201

Если ты можешь убедиться, что транзакция 2 при выполнении видела нужные тебе изменения Х, то да.
Если нет - то в общем случае нет (ничто не мешает серверам как-нить хитро реордерить поступившие транзакции для разрешения конфликтов, например).

agaaaa

Я тут, кстати, немного посамообразовывался и выяснил, что мне нужен более слабый вариант - PRAM (или FIFO) consistency. Но описал я всё верно.

agaaaa

Если ты можешь убедиться, что транзакция 2 при выполнении видела нужные тебе изменения Х, то да.
Ну вообще это всё где-то должно быть описано. Спекулировать я и сам могу, но хотелось бы знать наверняка.
Если нет - то в общем случае нет (ничто не мешает серверам как-нить хитро реордерить поступившие транзакции для разрешения конфликтов, например).
Собственно я в этом не уверен.

marat7256

Как операции с таблицей 1 влияют на операции с таблицей 2?

agaaaa

Допустим они не связаны.
(Ну то есть понятно, что они связаны через код клиента 1, но его код, разумеется, не может повлиять на БД)

6yrop

Если нет - то в общем случае нет (ничто не мешает серверам как-нить хитро реордерить поступившие транзакции для разрешения конфликтов, например).
Неверно пишешь. Иначе нарушается Durability. По условию задачи Транзакция2 идет после ТранзакцияX. Клиент2 видит результаты Транзакция2, следовательно, он должен видеть результаты всех транзакций, которые прошли до Транзакция2. Это если SERIALIZABLE.
Те, которые "без транзакций", могут не быть в SERIALIZABLE.

agaaaa

ТранзакцияX. Клиент2 видит результаты Транзакция2, следовательно, он должен видеть результаты всех транзакций, которые прошли до Транзакция2. Это если SERIALIZABLE.
Это ты где нашёл?

katrin2201

> По условию задачи Транзакция2 идет после ТранзакцияX.
"По условию задачи" не уточняется даже происходит ли это все в одном треде или нет.

agaaaa

"По условию задачи" не уточняется даже происходит ли это все в одном треде или нет.
Каждый клиент - в своём одном треде. Клиенты не обязательно на одной машине.

marat7256

Допустим они не связаны.
Тогда в чем смысл рассматривать транзакции с Таблицей 1, если вопрос только о Таблице 2?

agaaaa

Таблица 1 - что-то вроде семафора для доступа к таблице 2. Но, разумеется, БД об этом не знает.

katrin2201

> Каждый клиент - в своём одном треде. Клиенты не обязательно на одной машине.
Здравый смысл, говорит, что тогда да. Типа, при коммите появляется запись в журнале, и с этого момента она видна всюду. Так как поток один, то гарантируется порядок Тр1-ОпХ-Тр2 в журнале, и тогда все чики-пуки. Скорее всего, в реальном мире SQL Server'а все так и есть, но это только моя догадка.
Теоретически же, базе данных ничто не мешает положить ОпХ в журнал в произвольное относительно Тр1-Тр2 место, или вообще зареордерить даже после коммита (так как строки чтения/записи в ОпХ не перекрываются с Тр1-Тр2, то результат будет один и тот же вне зависимости от того, где именно в журнале находится ОпХ относительно Тр1-Тр2). Durability при этом нарушен никоим образом не будет.
Поэтому, в общем случае, я бы на это не полагался.
Данная проблема фиксится, если в каждом стейтменте ОпХ явно трогать строчку из пересечения working set'ов Тр1-Тр2. Тогда бд будет вынуждена энфорсить порядок.
> что-то вроде семафора для доступа к таблице 2.
Вообще, как-то это все fishy. Если ты пытаешься изобрести свои собственные локи, чтобы избавиться от длинных транзакций... То может просто потюнить транзакции в бд, или еще что? Результат то, все равно один и тот же будет (лок висящий на таблице два все время выполнения ОпХ что так что эдак, не?

6yrop

"По условию задачи" не уточняется даже происходит ли это все в одном треде или нет.
В условии задачи клиенты это клиенты базы данных. Для Клиент1 в условии описаны последовательные действия. X это транзакции из одного sql стейтмента. С точки зрения Клиент1 Транзакция2 идет после X. Если Клиент2 видит результаты Транзакция2, а результаты X не видит, то для этого клиента X исчезла, т.е. нарушение Durability.
Ты почему-то путаешь с ситуацией одновременных транзакций, когда ни один из клиентов не знает порядок, тогда, да, СУБД может делать свой порядок, но, если какой-либо клиент точно знает порядок, СУБД его не может поменять.

katrin2201

то для этого клиента X исчезла, т.е. нарушение Durability.
Нарушение Durability только если ОпХ совсем пропала из журнала.
А если же возможен такой реордеринг - Тр1 Тр2 ТрК2 ОпХ - то никто никуда не пропадал и дюрабилити не нарушена. К2 ее просто не видит, потому что с точки зрения БД он пришел до завершения ОпХ.
Возможен такой реордеринг может быть вполне, потому что все прочитанное/записанное К1, что при взаимном порядке Тр1 ОпХ Тр2, что при Тр1 Тр2 ОпХ будет иметь одни и те же значения. А про ТрК2 все, что мы знаем, это только то, что она идет после Тр2, то есть ничто не мешает получить Тр1 Тр2 ТрК2 ОпХ.
То, что говоришь ты, справедливо только если у ACID БД есть один большой глобальный лок на журнал (что должно быть верно для SQL Server и никакая конфликторазрешающая эвристика не реордерит записи в журнале в рамках допустимого (что скорее всего верно).
Но если рассматривать БД как строчки и набор локов на них, то один ACID никак тебе не поможет заэнфорсить визибилити, если ты будешь синхронизироваться на одном локе и пытаться прочитать то, что было записано синхронизируясь на другом локе.
> СУБД может делать свой порядок, но, если какой-либо клиент точно знает порядок, СУБД его не может поменять.
Чудо, СУБД не различает транзакции по клиентам. Для него все транзакции - как будто от разных клиентов. И то, что часть транзакций шла в одном потоке одного клиента - ей совершенно до балды, она не знает про это и увязать такое не может.
Единственные зависимости, которые она знает про транзакции - это зависимости по данным. А зависимости по данным в этом случае таковы, что допускают описанный выше реордеринг.

6yrop

Чудо
чудо, ты читать не умеешь

6yrop

ничто не мешает получить Тр1 Тр2 ТрК2 ОпХ.
Ага, после ТрК2 отрубили электричество. А у клиента1 "справка", что Х завершилась. Это, по-твоему, Durability?

katrin2201

Пускай отрубили. В ACID где то написано, что дюрабилити гарантируется только если запись попала в журнал бд? ACID вообще на этом уровне не оперирует.
Примера ради, пусть есть журнал, и некая очередь-неупорядоченное множество кандидатов в журнал. При коммите транзакция попадает в очередь, и известно, что попадание туда гарантирует тебе дюрабилити. А когда она попадет в журнал и полностью упорядочится относительно всех остальных транзакций - никто ничего не говорит. Гарантируется только то, что она попадет в журнал в таком порядке, что при реплее результат выполнения будет тот же самый.

6yrop

Тр1 Тр2 ТрК2 ОпХ
...
Для него все транзакции - как будто от разных клиентов.
А если К2==К1?

katrin2201

Ты не поверишь...

6yrop

если K1==K2, то в ТрК2 клиент читает из T2 и не видит те данные, которые он туда записал, бред же

katrin2201

Welcome to the thrilling world of concurrency/distributed computing...
Можешь про chubby почитать и вокруг, там уши схожих проблем отовсюду торчат.
Вообще, я уже писал, но еще раз уточню, что эти эффекты скорее всего ненаблюдаемы в случае традиционных однохостовых RDBMS.

agaaaa

Вообще, как-то это все fishy. Если ты пытаешься изобрести свои собственные локи, чтобы избавиться от длинных транзакций... То может просто потюнить транзакции в бд, или еще что? Результат то, все равно один и тот же будет (лок висящий на таблице два все время выполнения ОпХ что так что эдак, не?
Я ничего изобрести не пытаюсь. Просто вижу чужой код, который полагается на это свойство. Я в БД не эксперт, но такой подход меня напряг и я решил выяснить, оно гарантируется или нет.
SQL Server, кстати, умеет работать в нескольких репликах. Реплики, полагаю, транзакциями ещё более свободно обмениваются.

6yrop

ааа, NoSQL сожрали твой мозг. Скоро специалисты по distributed computing совсем потеряют остатки здравого смысла и связь с реальностью.

katrin2201

NoSQL - это ты написал. Чабби - это все же несколько не то.

kokoc88

Просто вижу чужой код, который полагается на это свойство.
Пример кода мог бы пролить свет на происходящее. Без этого не совсем понятно, что значит "Работаем с таблицей 2 без транзакций (опер Х)". Например, ADO.NET делает autocommit с каждым запросом (уровень изоляции берётся последний из текущего connection) - это "без транзакций"?

kokoc88

Если нет - то в общем случае нет (ничто не мешает серверам как-нить хитро реордерить поступившие транзакции для разрешения конфликтов, например).
Ты хочешь сказать, что если Клиент 1 после работы с таблицей 2 откроет новое SQL соединение, то в общем случае он не увидит результата своей работы?

agaaaa

Я уже посмотрел на доки к SQL. Там пишут, что если транзакцию явно не объявлять, каждый statement будет завёрнут в отдельную транзакцию.

agaaaa

Ты хочешь сказать, что если Клиент 1 после работы с таблицей 2 откроет новое SQL соединение, то в общем случае он не увидит результата своей работы?
А почему нет, если его балансировщик к другой реплике подключит?

Dasar

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

6yrop

если хочется увидеть результат своей работы, то появляется зависимость по данным. В обсуждаемом случае нет такой зависимости.
В рассматриваемой случае может быть Клиент1==Клиент2.

kokoc88

А почему нет, если его балансировщик к другой реплике подключит?
Просто так никто никого никуда не подключает. Я как бы указываю на недостаточность данных в твоём условии задачи. Вполне может быть, что ты зря напрягся и код правильный. (Если есть реплики и какой-то балансировщик, то ответ на твой вопрос вообще очевиден.)

kokoc88

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

agaaaa

Так расскажи очевидное и откуда ты его взял. Если я чего-то не указал в задаче, значит это что-то может быть каким угодно.

kokoc88

Если я чего-то не указал в задаче, значит это что-то может быть каким угодно.
Куда ещё очевиднее? Если может быть что угодно, значит, может быть что угодно (например, таблицы 1 и 2 находятся в разных не связанных между собой SQL инстансах).
Оставить комментарий
Имя или ник:
Комментарий: