2015-05-30 3 views
6

В PostgreSQL механизм MVCC concurrency control говорит, что:Почему MVCC требует блокировок для операторов DML

MVCC блокировки для запроса данных (чтение) не вступают в конфликт с блокировок для записи данных, и поэтому не читали никогда блоки пишущих и записные никогда не блокирует чтение

Итак, even for READ_COMMITTED, обновление оператор заблокируют в настоящее время затронутых строк так, никакой другая транзакция не может изменить их, пока текущая транзакция не зафиксируется или отката.

Если параллельная транзакция выдает UPDATE в заблокированных строках, вторая транзакция будет блокироваться до тех пор, пока первая не выпустит свои блокировки.

  1. Это такое поведение trying to prevent the write-write conflicts?

  2. Утерянные обновления все еще могут произойти в READ_COMMITTED, так как после совершения первой транзакции вторая перезапишет строку (даже если база данных изменилась между началом запроса UPDATE и концом запроса). Поэтому, если потерянные обновления все еще возможны, почему вторая транзакция должна ждать? Не удалось ли использовать снимки на уровне строк для хранения изменений незавершенных транзакций, чтобы избежать транзакций, ожидающих освобождения блокировок записи?

ответ

3

Ответ на первый вопрос: Да. Никакая СУБД не может поддерживать грязную запись; если одновременно выполняются две транзакции T1 и T2, а T2 перезаписывает обновление из T1, тогда система не может обрабатывать случай, когда T1 впоследствии выдает ROLLBACK, поскольку обновление T2 уже произошло.

Чтобы избежать грязной записи, первоначальное определение изоляции моментальных снимков было «первым побеждением коммиттера» - то есть конфликтующие записи могли бы произойти, но только первая транзакция для выдачи COMMIT могла бы - все остальные конфликтующие транзакции должны были бы ROLLBACK. Но эта модель программирования несколько проблематична, если не расточительна, поскольку транзакция может обновить значительную часть базы данных только для того, чтобы отказаться от возможности COMMIT в конце. Таким образом, вместо того, чтобы «первый коммиттер выигрывает», большинство систем СУБД, которые поддерживают MVCC, реализуют «первые попытки обновления», используя довольно традиционную двухфазную блокировку.

+0

Но грязные чтения не могут произойти, так как мы на READ_COMMITTED. Я размышлял, почему бы не обновить изолированные копии и просто очистить их в момент фиксации. Прямо сейчас, в PostgreSQL, второй tx просто перезаписывает 1-й, но также происходит блокировка. Почему бы просто не использовать моментальные снимки с сеансом и не блокировать на этом уровне изоляции. –

+0

Я думаю, что вы подразумеваете под «обновлением изолированных копий», будет соответствовать «первым победам коммиттера». И система может реализовать это, но модель программирования нечетна, поскольку каждая транзакция должна быть подготовлена ​​для обработки случая, когда каждая модификация «работала» (т. Е. Она заполняла и не возвращала ошибку), но транзакция не может быть зафиксирована , –

+0

Я полагаю, что модель блокировки легче принять, потому что каждая база данных уже имеет иерархию блокировки. Как вы уже упоминали ранее, это не только данные строки, но и все индексы. –

Смежные вопросы