Реализация MVCC - Multi-Version Concurrency Control в версии 6.5 подробно описана в документации.
Здесь я привожу выдержку из письма Вадима Михеева (автора MVCC) для русскоязычных пользователей как дополнение к оригинальной документации.
Date: Mon, 09 Aug 1999 16:08:19 +0800 From: Vadim MikheevTo: Oleg Bartunov Subject: Re: indices grow ! ----skipped ------ А что его понимать-то! -:) Основное что надо помнить: Запрос (те Query - то что читает записи из базы используя Seq/Index scans и отбирает их в соответствии с условиями в WHERE используя joins, subselects etc) видит (те возвращает) только те записи, который были живы в момент старта запроса(READ COMMITTED)/транзакции(SERIALIZABLE). Всё остальное лишь производное -:) 1. Если запрос был инициирован командой (statement) SELECT, то эти записи и будут возвращены, безо всякой гарантии, что они живы в данный момент или не будут изменены/удалены до окончания транзакции, в которой был дан этот самый SELECT. 2. Если запрос служит для выполнения команды UPDATE/DELETE, то: а. если запись (которую вернул запрос) изменена работающей транзакцией, то мы будем ждать её завершения; в случае abort'а мы попытаемся её изменить (если кто-либо другой не успеет раньше нас), в случае commit'а - см. б.; б. если запись (которую вернул запрос) изменена закомиченной транзакцией, то в случае SERIALIZABLE isolation level мы делаем ABORT, а в случае READ COMMITTED идём по цепочке версий записи, берём живую (если есть, те не стёрта вообще) и проверяем что она подходит под условия запроса: подходит - делаем то что требуется командой (UPDATE/DELETE), иначе - ничего с ней не делаем, продолжаем выполнение команды дальше. Это поведение по-умолчанию. Его можно разнообразить с помощью SELECT FOR UPDATE (действует как UPDATE/DELETE, только что не меняет/стирает записи, а помечает - локирует - их) и/или LOCK TABLE in so many modes -:) Vadim