Фантомное чтение (phantom read). Этот феномен очень похож на неповторяющееся чтение, но здесь идет чтение нескольких строк. Первая транзакция делает выборку набора строк. После этого приходит вторая транзакция и удаляет или добавляет строки попадающие в эту выборку. Вторая транзакция фиксирует свои изменения. После этого первая транзакция снова делает ту же самую выборку и уже получает другой набор строк - их стало либо больше, либо меньше чем при первой выборке, так как вторая транзакция добавила / удалила строки.
Фантомное чтение возникает, только когда добавляются строки, попадающие под условие выборки. Дело в том, что такие строки нельзя заранее заблокировать, отсюда и разница между двумя аномалиями.
Сошлюсь на стандарт:
P3 (“Phantom”): SQL-transaction T1 reads the set of rows N that satisfy some <search condition>. SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the <search condition> used by SQL-transaction T1. If SQL-transaction T1 then repeats the initial read with the same <search condition>, it obtains a different collection of rows.
А удаление - это случай неповторяющегося чтения:
P2 (“Non-repeatable read”): SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified value or discover that the row has been deleted.
Ну как можно утверждать, что "такое-то значение такого-то параметра приводит к таким-то ожиданиям"? Нехорошее значение может привести к избыточно большому объему работы, которое может привести к тому, что каких-то ожиданий станет больше, чем могло бы. Сплошная спекуляция, короче.
Как это формализовать для автоматической диагностики - не знаю. По идее, признаком плохой настройки являются пики дисковой активности (но кто даст гарантию, что зарегистрированный пик вызван именно контрольной точкой?) и в целом избыточная дисковая активность (но как понять без экспериментов с разными настройками на одной и той же нагрузке, что активность избыточна?).
Мм, да, я имел в виду ситуацию, когда две транзакции действительно пересеклись по данным. PostgreSQL на уровне Repeatable Read перечитает строку, которая была заблокирована, и, если она изменилась, оборвет транзакцию.
Я бы так сказал: про рекомендательные блокировки надо вспомнить, когда потребуется сделать что-то такое, что на обычные блокировки ложится плохо. Не всегда может найтись подходящая таблица.
И еще - рекомендательные блокировки работают быстрее блокировок строк, поскольку никак не меняют страницы данных. В каких-то случаях это может оказаться важным для быстродействия.
А как насчет gap lock и Next-Key Locks в Mysql? Не являются ли они по сути теми же предикатными блокировками?
Возможно я неточно выразился. Похожие по смыслу блокировки есть, но их реализация радикально отличается от предложенного в статье. В PostgreSQL (и, насколько я представляю, в MySQL тоже) они опираются на индекс. Только в PostgreSQL это даже и не блокировка, а способ отследить зависимость.
Хотя опять же непонятно, если Mysql реализует честный MVCC, то зачем ему вообще такого рода блокировки.
PostgreSQL в такой ситуации оборвет одну из транзакций при попытке фиксации. Возможно, в MySQL этого пытаются избежать с помощью блокировки. Но тогда после снятия блокировки транзакция должна перечитывать новое состояние; не знаю, как с этим в MySQL, не исследовал.
А так ли это? Можно цитату из стандарта, где это прямо говорится?
Конечно можно цитату:
The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions. A serial execution is one in which each SQL-transaction executes to completion before the next SQL-transaction begins.
Я думаю, что согласно Стандарту, Serializable - это как раз - таки уровень, на котором не допускаются грязное, неповторяющееся и фантомное чтение. И не более того.
Самолёт преодолел точки и затмил солнце, расходимся.
аффторский
Дивный новый мир: нейросеть что-то там нагенерила, автор даже не удосужился проверить.
Сложно-то как. А почему не посмотреть количество прочитанных буфером простым explain (analyze, buffers)?
(К слову, для ожиданий есть pg_wait_sampling, а для просмотра плана работающего запроса - pg_query_state).
Про красивую и осмысленную визуализацию данных неплохо почитать Эдварда Тафти.
Террабайт что-то до сих пор никто не.
...и немедленно выполнил.
«Постгря», &$#
Фантомное чтение возникает, только когда добавляются строки, попадающие под условие выборки. Дело в том, что такие строки нельзя заранее заблокировать, отсюда и разница между двумя аномалиями.
Сошлюсь на стандарт:
А удаление - это случай неповторяющегося чтения:
Первое апреля еще не скоро!
Продолжайте!
Если понадобится глоссарий по базам данных, у нас есть небольшой. И отдельно по PostGIS я делал, когда редактировал перевод книги.
Дело благое. А накопленный глоссарий не хотите опубликовать?
А планы, внезапно, от Greenplum-а.
Возможно в стандарте, но невозможно в PostgreSQL (как и в других СУБД, которые используют изоляцию на основе снимков).
Поскольку вопрос риторический, просто замечу, что типографика на картинке шикарна и в целом отражает состояние умов!
Ну как можно утверждать, что "такое-то значение такого-то параметра приводит к таким-то ожиданиям"? Нехорошее значение может привести к избыточно большому объему работы, которое может привести к тому, что каких-то ожиданий станет больше, чем могло бы. Сплошная спекуляция, короче.
А на тему оптимальной настройки контрольной точки можно диссертации писать. Мое изложение традиционного подхода есть в https://postgrespro.ru/education/books/internals, раздел 10.6. Другой взгляд (практика!) есть в https://postgrespro.ru/education/books/monitoring, раздел 5.7.
Как это формализовать для автоматической диагностики - не знаю. По идее, признаком плохой настройки являются пики дисковой активности (но кто даст гарантию, что зарегистрированный пик вызван именно контрольной точкой?) и в целом избыточная дисковая активность (но как понять без экспериментов с разными настройками на одной и той же нагрузке, что активность избыточна?).
Мм, да, я имел в виду ситуацию, когда две транзакции действительно пересеклись по данным. PostgreSQL на уровне Repeatable Read перечитает строку, которая была заблокирована, и, если она изменилась, оборвет транзакцию.
А с MySQL я бы начал разбираться с изучения https://jepsen.io/analyses/mysql-8.0.34. Там много интересного.
Я бы так сказал: про рекомендательные блокировки надо вспомнить, когда потребуется сделать что-то такое, что на обычные блокировки ложится плохо. Не всегда может найтись подходящая таблица.
И еще - рекомендательные блокировки работают быстрее блокировок строк, поскольку никак не меняют страницы данных. В каких-то случаях это может оказаться важным для быстродействия.
Возможно я неточно выразился. Похожие по смыслу блокировки есть, но их реализация радикально отличается от предложенного в статье. В PostgreSQL (и, насколько я представляю, в MySQL тоже) они опираются на индекс. Только в PostgreSQL это даже и не блокировка, а способ отследить зависимость.
PostgreSQL в такой ситуации оборвет одну из транзакций при попытке фиксации. Возможно, в MySQL этого пытаются избежать с помощью блокировки. Но тогда после снятия блокировки транзакция должна перечитывать новое состояние; не знаю, как с этим в MySQL, не исследовал.
Конечно можно цитату:
The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions. A serial execution is one in which each SQL-transaction executes to completion before the next SQL-transaction begins.
Ни в коем случае.