Чтобы ответить на это, я должен объяснить кое-что о PostgreSQL внутренностях.
В PostgreSQL строки никогда не обновляются на месте. Скорее каждый UPDATE
создает новую версию строки. Точно так же DELETE
не удаляет строку, но помечает ее как недействительную.
Каждая версия строки содержит идентификатор транзакции, которая ее создала, и транзакции, которая пометила ее как недействительную. Вместе эти идентификаторы транзакций определяют видимость версии строки.
COMMIT
и ROLLBACK
вообще не касаются таблицы, они только отмечают транзакцию, совершенную или прерванную в журнал фиксации .
Теперь запрос, который читает версию строки, должен обратиться к журналу фиксации, чтобы определить, может ли он увидеть версию строки или нет. Например, если транзакция, которая создала версию строки, откатывается, версия строки невидима.
Вы можете себе представить, что это создаст много трафика c в журнале фиксации, что снизит производительность , если не было никакой оптимизации на месте: если оператор, обращающийся к строке, обнаружит, что транзакция создания или удаления завершена, он установит так называемый бит подсказки в версии строки. Последующим читателям теперь не нужно больше просматривать журнал фиксации.
Ваш запрос первым прочитал некоторые строки в таблице, поэтому он установил эти биты подсказок. Эта модификация делает блок, содержащий версию строки, «грязным», то есть его необходимо записать в хранилище.
Это объясняет, как запросы на чтение могут закончить запись данных в PostgreSQL. По этой причине часто рекомендуется VACUUM
таблица после массового изменения данных: это займет бремя установки битов подсказки от первого считывателя.