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

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

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

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

26 ответов

65 просмотров

Тогда отличаются — технически, на 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) — потому что в несериализуемых расписаниях они неизбежно будут.

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

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

Коллеги, я тут для личных нужд пошел ставить MQTT сервер, пощупал mosquitto, но ужаснулся отсутствию такой банальности, как HTTP API для посмотреть список топиков. А тут что,...
Maksim Lapshin
13
Но, может, есть уже проверенная? Наши требования такие: 1. Сообщения должны приходить из Инста в CRM оду 2. Должна быть возможность подключить несколько экаунтов Инстаграм. Р...
Alexander Sharoiko MSE / Александр Шаройко
13
Вопрос на перед, на следующую пятницу. Сколько строк кода можно вешать на одного программиста, понятно что если проект хорошо написан то можно и миллион. Но есть же где то пре...
AlekseyK Kluchnikov
31
Немного оффтопа: а кто на чем сидит для осдева в плане ide/редактора? Последнее время сидел на vscode, но я его прям не могу нормально воспринимать, перешел на сlion, но меня...
Evg Resh
29
Как думаете через какой сервис они верифицируют?
inc.
5
Это может быть все-таки не флудвейт? у меня ботфазер принимает изменения и отображает даже что они изменились, на видео видно что он прислал якобы уже измененное описание, н...
OVERLINK
13
День добрый, подскажите пожалуйста, есть ли какой-то способ сказать ребару не компилировать определённое приложение? Всю доку их перечиатл ничего подобного не нашёл
Кирилл
14
Добрый день! Подскажите, каким сборщиком фронта для OctoberCMS кто пользуется? Я имею ввиду сборщики, с которыми можно работать по стандартной схеме директорий октября. Я испо...
Николай Афанасенко
2
Вопрос: Здравствуйте! У меня возникла проблема с использованием плагина Mall в OctoberCMS. Я использую все файлы и компоненты в их исходном виде, без изменений. Однако на стр...
𐩱𐩪𐩣𐩱𐩲𐩺𐩡
8
Я правильно понимаю что нет способов получить список ожидающих заявок на вступление в группу с помощью бота из mtproto?
Шамиль Прилов
9
Карта сайта