72 похожих чатов

Привет А правильно понимаю, что читающие транзакции режимов rr и Serializable

ничем не отличаются?

отличия проявляются только у пишущих

26 ответов

19 просмотров

Тогда отличаются — технически, на RR не используются SIRead locks. К каким отличиям в их поведении это приводит — см. https://wiki.postgresql.org/wiki/SSI#Rollover Да, в PostgreSQL есть специальный режим BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY DEFERRABLE;, в котором после того, как PostgreSQL гарантировал, что аномалии от этого невозможны, транзакции "внутри" работают точно так же, как на RR (не используют SIRead locks вообще).

RAFIZ- Автор вопроса
Yaroslav Schekin
Тогда отличаются — технически, на RR не используют...

я этот пример воспроизвёл на постгресе. Т1 упала при коммите…

RAFIZ
screenshot я этот пример воспроизвёл на постгресе. Т1 упала п...

Какой именно из обсуждавшихся? Или прямо тот, что по ссылке?

Лог двух сессий: /* Session1 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- T1 /* Session1 */ UPDATE rollover SET n = n + (SELECT n FROM rollover WHERE id = 2) WHERE id = 1; /* Session2 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- T2 /* Session2 */ UPDATE rollover SET n = n + 1 WHERE id = 2; /* Session2 */ COMMIT; /* Session2 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY; -- T3 SELECT count(*) FROM pg_class; /* Session1 */ COMMIT; /* Session2 */ SELECT n FROM rollover WHERE id IN (1, 2); -- Получаю: ERROR: could not serialize access due to read/write dependencies among transactions DETAIL: Reason code: Canceled on conflict out to pivot 11820632, during read. HINT: The transaction might succeed if retried. Всё 1:1 как написано — проверяйте, что Вы делаете не так.

RAFIZ- Автор вопроса
Yaroslav Schekin
Лог двух сессий: /* Session1 */ BEGIN TRANSACTION...

1:1 всё так сделаю. скрины ж привёл

RAFIZ
1:1 всё так сделаю. скрины ж привёл

У Вас не видно последовательности и сессий на этих screenshots. Прямо скопируйте то, что я показал, в две сессии какого-то клиента (ну или копируйте в psql по одному), и выполните соответствующие запросы по одному, внимательно. > укажите свою версию 15.4. Но это обязано так работать (на последних minors), начиная с 9.1 — это простейший тест.

RAFIZ- Автор вопроса
Yaroslav Schekin
У Вас не видно последовательности и сессий на этих...

какая должна быть последовательность сессий? у меня обе сессии были открыты ещё до создания таблицы тестируемой а потом порядок транзакций точно такой же, как по ссылке версия у меня тоже PostgreSQL 15.4 on aarch64-unknown-linux-musl, compiled by gcc (Alpine 12.2.1_git20220924-r10) 12.2.1 20220924, 64-bit

RAFIZ
какая должна быть последовательность сессий? у мен...

У меня же указана, какая — вот, указал для каждого запроса. > у меня обе сессии были открыты ещё до создания таблицы тестируемой Это не имеет значения — главное, чтобы открытых транзакций в них не было (и "забытых" паралелльных транзакций, в которых Вы это же тестировали — тоже, а то мало ли... ;) ). > а потом порядок транзакций точно такой же, как по ссылке Ну вот и посмотрите, как это должно работать (и у меня работает) при таком порядке. Да попробуйте ещё раз с самого начала (выполните DROP этой таблицы), что тут думать. ;)

RAFIZ- Автор вопроса
Yaroslav Schekin
У меня же указана, какая — вот, указал для каждого...

ёёпт:) я сейчас удалю весь контейнер для эксперимента, в абсолютно пустой базе создам таблу и сделаю как в ссылке, посмотрим. upd: скачал, на всякий случай для справки указываю что получил WARNING: there is no transaction in progress то есть в исходный момент 0 транзакций в обеих сессиях

RAFIZ- Автор вопроса
RAFIZ
ёёпт:) я сейчас удалю весь контейнер для экспериме...

в общем, если хоть в Т1, хоть в Т2 после обновления прочитать эти данные, а потом закоммитить — падает именно Т1

RAFIZ- Автор вопроса
Yaroslav Schekin
У меня же указана, какая — вот, указал для каждого...

у Т3 же снепшот берётся в момент выполнения select count(*) from pg_class; ?

RAFIZ
ёёпт:) я сейчас удалю весь контейнер для экспериме...

WARNING: there is no transaction in progress Нет, стоп. ;) Этого Вы не должны видеть (это будет, если выдать COMMIT; или ROLLBACK; в сессию, где нет активной транзакции).

RAFIZ
в общем, если хоть в Т1, хоть в Т2 после обновлени...

Ну так сам пример у Вас воспроизводится правильно, так?

RAFIZ- Автор вопроса
Yaroslav Schekin
WARNING: there is no transaction in progress Нет...

> Этого Вы не должны видеть (это будет, если выдать COMMIT; или ROLLBACK; в сессию, где нет активной транзакции). ну я так и сделал. чтоб продемонстрировать что активных транзакций не было (вы выше предполагали что я мб чёт забыл закрыть)

RAFIZ- Автор вопроса
Yaroslav Schekin
Ну так сам пример у Вас воспроизводится правильно,...

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

RAFIZ
да. но почему чтение после обновления всё ломает —...

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

RAFIZ- Автор вопроса
Yaroslav Schekin
> в общем, в сообщении со скриншотами всё правильн...

вы можете не перепечатывать а просто в Т1 после апдейта добавить чтение всей таблице. и то же самое в Т2 тоже после апдейта 95% кода у вас уже есть (он взят из примера по ссылке)

RAFIZ- Автор вопроса
Yaroslav Schekin
> в общем, в сообщении со скриншотами всё правильн...

``` /* Session1 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- T1 /* Session1 */ UPDATE rollover SET n = n + (SELECT n FROM rollover WHERE id = 2) WHERE id = 1; /* Session1 */ select * from rollover ; /* Session2 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- T2 /* Session2 */ UPDATE rollover SET n = n + 1 WHERE id = 2; /* Session2 */ select * from rollover ; /* Session2 */ COMMIT; /* Session2 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY; -- T3 /* Session2 */ SELECT count(*) FROM pg_class; /* Session1 */ COMMIT; /* Session1 */ ERROR: could not serialize access due to read/write dependencies among transactions DETAIL: Reason code: Canceled on identification as a pivot, during commit attempt. HINT: The transaction might succeed if retried. ```

Во-первых, заметьте, что тут не нужна T3 (то же самое получается). Во-вторых... мы же уже обсуждали именно этот случай, или мне кажется? Ладно, как бы там ни было... /* Session1 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- T1 /* Session1 */ UPDATE rollover SET n = n + (SELECT n FROM rollover WHERE id = 2) WHERE id = 1; /* Session1 */ SELECT * FROM rollover; /* Session2 */ BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- T2 /* Session2 */ UPDATE rollover SET n = n + 1 WHERE id = 2; /* Session2 */ SELECT * FROM rollover; /* Session2 */ COMMIT; /* Session1 */ COMMIT; Допустимые расписания (как и то, что каждая транзакция должна видеть при чтении после UPDATE): T1 T2 1. (1, 100), (2, 10) ----> (1, 110), (2, 10) ----> (1, 110), (2, 11) T2 T1 2. (1, 100), (2, 10) ----> (1, 100), (2, 11) ----> (1, 111), (2, 11) Так вот если разрешить выполнение по этому сценарию, то (несмотря на совпадение конечного результата с первым расписанием), транзакции будут видеть после своих update следующее: T1: (1, 110), (2, 10) T2: (1, 100), (2, 11) и ни одному из этих расписаний такое не соответствует — поэтому первую PostgreSQL откатывает.

RAFIZ- Автор вопроса
Yaroslav Schekin
Во-первых, заметьте, что тут не нужна T3 (то же са...

то есть опять банальное раскладывание по возможным комбинациям очерёдности даёт все ответы…

RAFIZ
то есть опять банальное раскладывание по возможным...

Естественно, оно всегда даёт все ответы. :) Да, кстати, я вот в прошлый раз написал, что поиск цикла в графе предшествования — это просто shortcut. Но это не совсем так, т.е. это так только для того человека, который анализирует/проверяет сериализуемость — а алгоритмы обеспечения serializability как раз и строятся на предотвращении либо поиске (и разрыве, путём отката транзакций) таких циклов (или характерных для них структур, как это делает SSI) — потому что в несериализуемых расписаниях они неизбежно будут.

Похожие вопросы

Обсуждают сегодня

Какого хера? /Sources/App/Modules/User/Models/UserLinkApple.swift:21:20: warning: stored property '_id' of 'Sendable'-conforming class 'UserLinkApple' is mutable @ID(...
Alexander Sherbakov
14
У тебя в конфиге нигде нет deny all; или вообще любого deny?
Alexander Sherbakov
10
Портфолио: Зовут меня Александр, мне 36 лет. Город Пушкино. Общий рабочий стаж: ~14 лет Уровень квалификации: Senior Full-stack developer Где прочесть мой код? https://github....
Magic
10
Портфолио: Зовут меня Александр, мне 41 год. Город Киров. Общий рабочий стаж: ~14 лет Уровень квалификации: Senior Full-stack developer Где прочесть мой код? https://github.co...
Magic
11
Приветствую всех, есть вопросик. Передали проект на OctoberCms, без инсталяшки в полуразвернутом виде, нужно было залить бекап бд, после залития бд, оказалось, что части строк...
Лео
14
Подскажите, пожалуйста, где в backende, или не в нем можно дату поправить? Логирует действия не в том часовом поясе
Лео
7
Есть магистры regex в чате? Задача: нужно написать regex который мэтчит полные (без сокращений по типу ::1/128) ipv6 адреса кроме 2001:0df7:cef7:29f7:52f7:adf7:2cf7:4ff7, при ...
Илья
5
люди а напомните, пожалуста, как называется алгоритм поиска текста который допускает ввод ошибок? Например есть несколько строк: Trigun Trigun: Stumpeede Мне нужно что бы ...
Куся 🌿⃤ __UKS
2
посыпаю голову пеплом =) https://docs.vapor.codes/advanced/files/?h=stream#files
Seryoga
10
Всем привет В общем надо на странице вакансии вывести вакансии с hh, но когда я пишу код в разделе Code ошибка Invalid URL format. The URL should start with the forward slash...
A da
1
Карта сайта