= 10 where y = 5; [не коммитит]
Поток 2:
update t set x = x+1 where y = 5;
Поток 1:
commit;
вроде как, второй поток должен (read commited по дефолту) увидеть ещё не-модифицированную строку, и встать в очередь на блокировку; но когда дождётся, то ему придётся перепроверять, верно ли до сих пор, что y = 5? или тут это как-то по-другому работает?
Почитайте https://www.postgresql.org/docs/current/transaction-iso.html#XACT-READ-COMMITTED , там всё описано (я не знаю, что Вы имеете в виду под "перезапусками" / как это работает в Oracle, поэтому не могу точно сказать). > Это PG "умнее" и просто триггер лишний раз не запускает? Before update trigger запускается после того, как row удаётся заблокировать, вроде (и update же в любом случае выполняется однократно, откуда там два запуска?).
ну вот в моём примере: * второй поток ищет строку с y = 5 * видит только ту версию, которая была до обновления (т.к. первый поток ещё не сказал commit) * видит что эта строка заблокирована * висит на блокировке * дожидается коммита в первом потоке * опа, а теперь в той строке (в новой версии) уже y = 10, значит апдейтить её не надо вот эту вторую проверку Кайт называет "перезапуском". Собственно, ваша ссылка рассказывает то же самое. UPDATE, DELETE, SELECT FOR UPDATE, and SELECT FOR SHARE commands behave the same as SELECT in terms of searching for target rows: they will only find target rows that were committed as of the command start time. However, such a target row might have already been updated (or deleted or locked) by another concurrent transaction by the time it is found. In this case, the would-be updater will wait for the first updating transaction to commit or roll back (if it is still in progress). If the first updater rolls back, then its effects are negated and the second updater can proceed with updating the originally found row. If the first updater commits, the second updater will ignore the row if the first updater deleted it, otherwise it will attempt to apply its operation to the updated version of the row. The search condition of the command (the WHERE clause) is re-evaluated to see if the updated version of the row still matches the search condition.
Привет! Если ты интересуешься технологиями, я хотел бы порекомендовать тебе канал про техническую сторону разработки. Там ты найдешь много интересных видео и статей о новых технологиях, программировании и других темах. 📺🔧 Там есть много видео и статей, которые легко понять даже для новичков. 🙌 И самое крутое, что они всегда в курсе последних трендов и новинок в мире технологий. 😎💡 Так что, если ты хочешь быть в курсе всех новостей и тенденций в мире технологий, заходи на этот канал! Там тебя ждет много интересного и полезного контента. 💻📱 А вот сама ссылка, чтобы ты смог быстро найти этот канал: [ссылка]. Удачи и приятного просмотра! 😉👍
@Ilya_Portnov: @floyd_rose Роман Жарков @confguru @Komzpa @obartunov
> вот эту вторую проверку Кайт называет "перезапуском". Я слышал, что в Oracle эти самые "перезапуски" — это что-то совсем другое. > is re-evaluated to see if the updated version of the row still matches the search condition. И мне непонятно, почему это "перезапуск", по сути — повторно вычисляется только условие, и только для [новой версии] конкретной записи. Соответственно, ни на какие триггеры это никак не влияет.
> вот эту вторую проверку Кайт называет "перезапуском". Я слышал, что в Oracle эти самые "перезапуски" — это что-то совсем другое. Edit: вот, например: https://dba.stackexchange.com/a/91398 > is re-evaluated to see if the updated version of the row still matches the search condition. И мне непонятно, почему это "перезапуск", по сути — повторно вычисляется только условие, и только для [новой версии] конкретной записи. Соответственно, ни на какие триггеры это никак не влияет.
Я вот сижу и думаю -- получается, что в некоторых случаях постгрес можэт увидеть пол-транзакцыи? То есть у нас в таблицэ value = 3 и 6. Первый update обновляет все value=value+1, и идёт (так получилось) по возрастанию. Второй -- обновляет все нечётные value, делает value=-value , и идёт (так получилось) по убыванию. Первый нашёл value=3, сделал value=4. Второй нашёл value=6, пропустил его. Первый нашёл value=6, сделал value=7 Второй нашёл value=3, но обновлённый незакоммиченной транзакцыей. Завис. Первый дошёл до конца, закоммитил транзакцыю. Второй увидел, что значение value=3 удалено, пропустил его (возможно, увидел, что есть value=4, пропустил и его). Итого: с точки зрения транзакцый состояние таблицы -- сначала value=3,6 после коммита -- 4,7 По идее -- второй update должэн увидеть или первое или второе. И сделать состояние или -3,6 или 4,-7 А он видит 6 и 4, то есть половины результатов транзакцыи!
Нет никакой пол транзакции, есть данные до выполнения параллельной транзакции и после ее фиксации. Аномалия неповторяющегося чтения это нормально для read commited
> Итого: с точки зрения транзакцый состояние таблицы -- сначала value=3,6 после коммита -- 4,7 Ну так это всё и есть, что тут удивительного? Более того, документация приводит аналогичный пример: More complex usage can produce undesirable results in Read Committed mode. For example, consider a DELETE command operating on data that is being both added and removed from its restriction criteria by another command, e.g., assume website is a two-row table with website.hits equaling 9 and 10: BEGIN; UPDATE website SET hits = hits + 1; -- run from another session: DELETE FROM website WHERE hits = 10; COMMIT; The DELETE will have no effect even though there is a website.hits = 10 row before and after the UPDATE. This occurs because the pre-update row value 9 is skipped, and when the UPDATE completes and DELETE obtains a lock, the new row value is no longer 10 but 11, which no longer matches the criteria.
> то есть половины результатов транзакцыи! Но я (наверное) понимаю, о чём Вы... да, snapshot-ы в READ COMMITTED "подтекают" (т.е. SELECT и UPDATE (или SELECT FOR UPDATE ) с теми же условиями могут видеть разные данные в рамках того же запроса (и это легко воспроизвести)) — но ничего, не соответствующего ISO SQL, тут нет. И да, в типичных реализациях RC в "блокировочниках" аномалии ещё более "волшебные" (они могут N раз "видеть" одну и ту же запись, например), кстати — и это тоже нормально (соответствует ISO SQL). Вот поэтому я всегда говорю, что для практической работы (на уровнях изоляции ниже S) с той или иной СУБД знать, что там пишет ISO SQL про уровни изоляции (опять-таки, кроме S) — бесполезно. Механизмы работы этих уровней в конкретной СУБД надо знать, и точка.
И, видимо, чтобы этого избежать -- Оракл при блокировке перезапускает (откатывает и перезапускает) ВЕСЬ update. Что само по себе очень весело.
Обсуждают сегодня