В транзакционной базе долгий запрос должен читать данные, пока записи продолжаются, не блокируя их. Какой механизм это обеспечивает?
Это обеспечивает многоверсионный контроль конкурентного доступа (MVCC). Читатель получает согласованный снимок данных и читает подходящие версии строк, пока писатели создают новые версии, поэтому обычные чтения не блокируют записи. Цена подхода — хранение старых версий, последующая очистка и необходимость учитывать длительные транзакции.
В ранних и блокировочных моделях конкурентного доступа чтение могло удерживать блокировки, а запись — ждать завершения долгого запроса. Для OLTP-систем это создавало задержки и снижало пропускную способность при одновременной работе множества транзакций.
MVCC возник как способ разделить версии данных по моментам времени. Он позволяет сохранять согласованность чтения без полного запрета параллельных изменений, что особенно важно для систем с большим количеством коротких записей и параллельных запросов.
Долгий запрос может читать тысячи или миллионы строк, пока другие транзакции изменяют те же таблицы. Если система использует только блокировки чтения, записи будут ждать завершения запроса; если блокировки записи имеют приоритет, читатель может получить непоследовательный результат или быть вынужден повторяться.
Простое разрешение читать текущие значения также опасно: разные части одного запроса могут увидеть разные состояния данных. Тогда итог зависит от момента чтения каждой строки, а агрегаты и соединения могут стать логически противоречивыми.
При MVCC изменение строки не просто заменяет старое значение для всех читателей. Система создаёт новую версию и сохраняет метаданные, по которым можно определить, для каких транзакций эта версия видима. Старую версию можно использовать читателям, чей снимок был сформирован до изменения.
Транзакция чтения получает правила видимости, обычно связанные с её снимком или временной отметкой. Для каждой строки выбирается версия, существовавшая в допустимый момент времени; версии, созданные более поздними или ещё не подтверждёнными транзакциями, не видны этому чтению.
Благодаря этому читатель обычно не устанавливает блокировки, препятствующие записи. Писатель также не меняет физически тот фрагмент данных, который требуется старому читателю, либо система предоставляет старую версию через журнал изменений, цепочку версий или другой механизм хранения.
MVCC не означает полного отсутствия блокировок. Блокировки могут применяться для конфликтующих изменений, структурных операций, проверки уникальности и некоторых уровней изоляции. Кроме того, при более строгой изоляции система может обнаружить конфликт сериализации и отменить одну из транзакций.
Старые версии нельзя хранить бесконечно. Фоновая очистка удаляет версии, которые уже не могут понадобиться ни одной активной транзакции. Очень долгий снимок удерживает такие версии, увеличивает объём хранения, нагрузку на очистку и иногда стоимость чтения.
Главный компромисс заключается в выборе между параллелизмом, объёмом служебных данных и строгостью изоляции. MVCC хорошо подходит для большинства обычных чтений, но не заменяет проектирование коротких транзакций, контроль конфликтов записи и выбор подходящего уровня изоляции.
В системе биллинга ночной отчёт выполняется около двадцати минут. Одновременно сервисы продолжают изменять платежи. Вариант с длительными блокировками чтения защищает от несогласованности, но заставляет операции записи ждать и приводит к росту задержек. Вариант чтения текущих значений без снимка быстрее, но отчёт может смешать данные до и после отдельных изменений.
Выбран MVCC-снимок на начало отчёта. Записи продолжаются, а запрос видит согласованную версию данных, существовавшую в пределах выбранной семантики изоляции. Команда дополнительно ограничила длительность отчётов и настроила наблюдение за удерживаемыми снимками, потому что иначе старые версии могли бы накапливаться и увеличивать нагрузку на очистку.
Нет, это зависит от уровня изоляции и реализации СУБД. При режиме, близком к чтению подтверждённых данных, отдельные операции или утверждения могут видеть разные снимки, если чтение выполняется в разные моменты. Более строгий режим обычно закрепляет снимок на транзакцию или обнаруживает конфликты, но может повысить вероятность ожидания или отката.
Они удерживают старую границу видимости. Пока такая транзакция активна, очистка не может удалить версии, которые потенциально нужны её чтению. В результате растут объём служебных данных, стоимость сканирования и нагрузка на фоновые процессы; поэтому долгие чтения следует ограничивать, разбивать или выполнять на специально подготовленном аналитическом контуре.
Нет. MVCC в первую очередь определяет видимость версий для чтения; конфликтующие записи требуют отдельной политики. Система может заблокировать одну запись, проверить версию перед сохранением, выявить конфликт при фиксации или допустить последнее успешное обновление — конкретное поведение определяется моделью конкурентного доступа и уровнем изоляции. Для критичных изменений приложение должно явно выбирать стратегию разрешения конфликтов.