Как мне реализовать MVCC?
Я нашел много ресурсов в Интернете, дающих общие обзоры концепций MVCC (многоуровневое управление параллелизмом), но нет подробных технических ссылок о том, как именно это должно работать или реализовываться. Существуют ли какие-либо документы в Интернете или книги в автономном режиме, которые содержат достаточно теории (и, в идеале, немного практической помощи), на которой можно основывать реализацию? Я хочу более или менее подражать тому, что делает PostgreSQL.
(Для информации, я буду реализовывать его в SAS с использованием SAS /Share - который предоставляет некоторые блокирующие примитивы и одновременный доступ для чтения / записи к базовому хранилищу данных, но ничего в плане изоляции транзакций или надлежащих функций СУБД. Если кто-то знаком с SAS / поделитесь и считает это невыполнимой задачей, пожалуйста кричите!)
4 ответа
Обработка транзакций: концепции и методы, а также транзакционные информационные системы: теория, алгоритмы и практика управления и восстановления параллелизма являются авторитетным источником обработки транзакций.
Обе эти книги также упоминаются в PostgreSQL Wiki.
Я написал сообщение в блоге об этом:
https://elliot.silvrback.com/implementing-your-own-transactions-with-mvcc
Я написал сообщение в блоге о том, как MVCC работает в PostgreSQL. По сути, таблица в PostgreSQL может хранить несколько версий одной и той же строки.
Более того, есть две дополнительные колонки:
- tmin - маркировка идентификатора транзакции, которая вставила строку
- tmax - маркировка идентификатора транзакции, которая удалила строку
Обновление выполняется путем удаления и вставки новой записи, и процесс VACUUM собирает старые версии, которые больше не используются.
Я реализовал MVCC на Java. Смотрите транзакцию , бегун и код mvcc .
Представьте, что каждая транзакция получает числовую метку времени, которая увеличивается для каждой транзакции. В этом примере у нас есть транзакции 1 и 2.
Транзакция 1 читает A и записывает значение (A + 1). Изоляция снимка создает временную версию (A), которой владеет транзакция 1. Временная метка чтения A устанавливается на транзакцию 1.
Если транзакция 2 появится в то же время и прочитает A, она также прочитает зафиксированную A — она не увидит A + 1, потому что она не была зафиксирована. Транзакция 2 может видеть версии A, которые == lastCommittedA и <= transaction 2.
Когда транзакция 2 читает A, она также проверит метку времени чтения A и увидит, что транзакция 1 существует, и проверит метку времени транзакции 1 < метку времени транзакции 2. Поскольку 1 < 2, транзакция 2 будет прервана, поскольку она уже зависит от старого значения A.