* FROM users WHERE email = ’test@test.com’
(тут пауза 5 сек)
INSERT INTO users (email) VALUES ('test@test.com')
Вторая транзакция:
INSERT INTO users (email) VALUES ('test@test.com')
Первая транзакция запускается сразу. Вторая в промежутке между запросами в первой транзакции
По идее результат второй транзакции, влияет на то, что возвращает первый запрос в первой транзакции. Но фейла не происходит.
Почему так?
Если во вторую транзакцию добавить select (такой же как у первой), то фейл происходит.
Как уровень изоляцыи выставляете?
serializable
Я спросил -- как.
Фигня, впрочем. Действительно, почему должна. Добавились две строчки, сначала из первой транзакцыи, затем из второй. Отличная сериализацыя.
Ну пока выполянется первая транзакция, и приходит вторая, которвя по идее влияет на то, что мог бы вернуть select в первой
Так вторая выполняется после первой. Ну, в рамках сериализацыи.
А почему добавления select заставляет фейлить?
Потому, что после этого ужэ не скажэшь что "вторая выполнилась после первой". Если бы это было так -- во втором селекте был бы этот результат, а его нет.
Я вот тут не понимаю. У меня вторая транзакции накладывается на первую и влияет на то как бы отработала первая
Вторая транзакцыя не влияет на первую потому, что считается, что она отработала после первой.
Так а почему тогда я добавляю select фэйл происходит, если вторая считается отработавшей после первой?
Потому, что она не получила результатов первой транзакцыи. А если бы отработала после -- то должна была получить.
Тогда в такой ситуации должно зафейлить? Но не фейлит Первая транзакция: BEGIN SET TRANSACTION ISOLATION LEVEL SERIALIZABLE INSERT INTO users (email) VALUES ('test@test.com') — в этот момент запускается вторая — COMMIT Вторая транзакция: BEGIN SET TRANSACTION ISOLATION LEVEL SERIALIZABLE SELECT * FROM users WHERE email = 'test@test.com’ COMMIT
Пробовал делать коммит второй до заврешения первой и после завершения. Не фейлит
Нет, почему бы? Вторая считается отработала до первой, всё в порядке.
А если коммит делать после коммита первой?
Да без разницы в данном случае.
Почему? Не понимаю механизм
Почему что?
Почему без разницы?
Потому, что это сработает.
Почему что?
> По идее результат второй транзакции, влияет на то, что возвращает первый запрос в первой транзакции. > Но фейла не происходит. > Почему так? Потому что всё это не имеет отношения к фундаментальному принципу / требованию serializable, вот и всё. В PostgreSQL apparent transaction order может не совпадать ни с последовательностью запуска транзакций, ни с последовательностью их завершения. И уж тем более он не обязан иметь хоть какое-то отношение к реальному времени.
>apparent transaction order может не совпадать ни с последовательностью запуска транзакций, ни с последовательностью их завершения. Интересно, кстати, а то, что он будет совпадать с календарным если время старта и завершэния полностью разделено (т.е. вторая началась после того, как завершылась первая) -- разработчики как-то пытаются гарнтировать -- или это просто пока вот так получается что совпадает из-за особенностей реализацыи?
Это, вполне возможно, вопрос определения. Первая попавшаяся ссылка: https://aphyr.com/posts/313-strong-consistency-models "In a serializable database, a transaction like read x is always allowed to execute at time 0, when x had not yet been initialized. Or it might be delayed infinitely far into the future! The transaction write 2 to x could execute right now, or it could be delayed until the end of time, never appearing to occur." ну и т.д., там есть примеры. В ISO SQL требования совпадения порядка в случае "вторая началась после того, как завершылась первая" тоже нет, насколько я помню. Но "обычные" (не распределённые) СУБД этот принцип всегда соблюдают, насколько я знаю.
В примере, как у Вас, если вначале выполнится первая тразакция, а потом вторая, то результат будет такой же, как при конкурентном выполнении, описанном Вами. Другими словами в данном случае можно придумать сериализованный порядок, при котором результат будет совпадать с Вашим результатом. Если добавить select во второй транзакции, то уже не получится подобрать последовательный запуск транзакции, при котором результат будет такой же, как у Вас. Проверьте сами, это просто.
>Другими словами в данном случае можно придумать сериализованный порядок Кстати, что-то подумал поутру -- возможно у вас тупик по поводу того, как postgresql это делает. Возможно, если бы я не знал как -- тожэ был бы в шоке, что за квантовая запутанность. На самом деле да, он запоминает критэрии поиска. И если потом какое-то обновление начинает обновлять что-то, подходящее под эти критэрии -- то начинает откатывать, какую откатывать -- выбирает по обстоятельствам. Это кроме правила создания снапшота для repeatable read -- что видны только данные (и все данные), у которых номер транзакцыи их записавшэй меньшэ либо равен текущей.
> Другими словами в данном случае можно придумать сериализованный порядок, Я бы дажэ сказал, не "можно", а "получилось". В соответствии с упрощёнными правилами "придумывания", которые реализованы в postgres и для которых когда-то кто-то доказал (в достаточной степени) их корректность.
Обсуждают сегодня