Как Greenplum расширяет MVCC-модель PostgreSQL для управления доступом к данным в многопользовательской среде, обеспечивая согласованность и изоляцию транзакций для нескольких сегментов в большом кластере. Преимущества моментальных снимков перед блокировками и их польза для резервного копирования.
MVCC и транзакции в Greenplum с PostgreSQL
Будучи основанной на PostgreSQL, о чем мы писали здесь, Greenplum также использует MVCC-модель (Multiversion Concurrency Control) управления параллельным доступом к нескольким версиям для обеспечения согласованности данных в многопользовательской среде. MVCC базируется на концепции так называемых моментальных снимках (снапшотах, snapshot), когда любой SQL-оператор видит версию базы данных, существующей на конкретный момент времени, независимо от текущего состояния данных. Это исключает несогласованность данных при выполнении транзакции, если в этот момент к этим же самым данным обращаются другие конкурирующие транзакции с целью их изменения или удаления. Таким образом, MVCC обеспечивает изоляцию транзакций для каждого сеанса базы данных и, в отличие от блокировки, не снижает производительность работы СУБД в многопользовательской среде: операции чтения и записи не мешают друг другу. В PostgreSQL это гарантируется даже для самого строгого SSI-уровня изоляции транзакций (Serializable Snapshot Isolation, сериализуемая изоляция снимков).
MPP-природа Greenplum вносит некоторые изменения в классическую MVCC-модель PostgreSQL, которая дает высокую степень параллелизма даже во время высокой активности и поддерживает согласованность для одного сервера СУБД, но не для нескольких сегментов. Поэтому Greenplum расширяет модель моментальных снимков, делая их распределенными и с синхронизацией во всех сегментах. При выполнении SQL-оператора в Greenplum координатор создает распределенный снапшот, который затем отправляется вместе с запросом в сегменты. Когда каждый сегмент получает распределенный снимок, он создает локальный, который сопоставляет идентификатор локальной транзакции (xid) с распределенным xid. Именно так Greenplum поддерживает согласованность данных во всем кластере.
Мы уже упоминали, что Greenplum предлагает два уровня изоляции транзакций: READ COMMITTED (по умолчанию) и REPEATABLE READ, когда SQL-запрос на выборку данных (SELECT) видит моментальный снимок базы данных в момент начала своего выполнения. При последующем выполнении SELECT в той же транзакции могут отображаться другие данные, если другие транзакции фиксируют изменения между SQL-операторами. При этом в REPEATABLE READ все операторы в одной транзакции могут видеть только те строки, которые зафиксированы до начала первого SELECT-запроса или запроса на изменение данных (INSERT, UPDATE или DELETE). Последующие операторы SELECT внутри одной транзакции всегда видят одни и те же данные без изменений, сделанных другими транзакциями, которые фиксируются, пока выполняется транзакция REPEATABLE READ. Все транзакции сохраняют моментальный снимок, определяемый следующими полями:
- xmin — самый ранний xid, который все еще активен. Все транзакции до этого идентификатора гарантированно будут либо зафиксированы, либо прерваны.
- xmax — первый неназначенный xid. Все транзакции, идентификаторы которых больше или равны xmax, еще не запущены и невидимы для моментального снимка.
- xip_list — активные идентификаторы транзакций xid на момент создания моментального снимка. У каждого кортежа есть xmin, для которого задан xid транзакции INSERT или UPDATE. Xmax для кортежа устанавливается как xid в командах UPDATE или DELETE.
Управление снапшотами
Транзакция в Greenplum может экспортировать моментальный снимок, который она использует. Пока транзакция остается открытой, другие транзакции могут импортировать snapshot, чтобы видеть то же состояние базы данных, что и исходная транзакция. Снимки экспортируются с помощью функции pg_export_snapshot() и импортируются с помощью команды SET TRANSACTION SNAPSHOT.
Важно еще раз подчеркнуть, что моментальные снимки транзакций не заменяют блокировки, а только гарантируют согласованность пользовательских данных. Кроме того, некоторые DDL-команды, такие как TRUNCATE и отдельные варианты ALTER TABLE, в т.ч. доступные в Greenplum 7, не безопасны для MVCC-подхода. Это обусловлено тем, что после фиксации этих транзакций таблица будет казаться пустой для параллельных транзакций, даже если они используют моментальный снимок, сделанный до фиксации. Поэтому AO-таблицы Greenplum и Arenadata DB, используют другую модель управления параллелизмом вместо MVCC, поскольку, в отличие от таблиц кучи, они предназначены для приложений с однократной записью и многократным чтением, что не предполагает обновления на уровне строк. Подробнее об этом мы рассказывали здесь и здесь.
Впрочем, снапшоты нужны не только для управления транзакциями в многопользовательской среде. Это еще и инструмент резервного копирования. Чтобы ускорить этот процесс, занимающий много времени для больших объемов данных, в утилиту резервного копирования gpbackup разработчики Greenplum добавили поддержку моментальных снимков. Используя экспортированные моментальные снимки, можно распараллелить создание резервных копий таблиц, гарантируя, что все они видят один снимок базы данных. Указать количество таких параллельных подключений при запуске утилиты gpbackup можно с помощью флага —jobs.
Однако, резервное копирование больших баз данных со множеством таблиц на практике не очень просто из-за блокировок. Если процесс создания резервных копий длится долго, что обычно и бывает в реальности, во время его выполнения внешние команды могут поставить в очередь блокировки на резервируемые таблицы. При этом, как мы уже отметили ранее, некоторые операторы, такие как TRUNCATE, блокируют последующие SQL-команды блокировкой ACCESS SHARE, ожидая завершения процедуры резервного копирования. Избежать этого можно, если непосредственно перед выполнением команды копирования таблицы получить блокировку ACCESS SHARE для нее с помощью оператора LOCK TABLE NOWAIT. При успешном выполнении этого оператора можно запускать команду COPY. Иначе транзакция прерывается, и таблица передается рабочему процессу, который собрал все блокировки ACCESS SHARE в начале резервного копирования, и может безопасно выполнять команды, не беспокоясь о взаимной блокировке. Подробнее про резервное копирование и обеспечение высокой доступности этой MPP-СУБД читайте в нашей отдельной статье.
Если транзакция прервана из-за ошибки LOCK TABLE NOWAIT, ее моментальный снимок больше недействителен. Без возможности импортирования снапшота с помощью команды SET TRANSACTION SNAPSHOT начало новой транзакции означало бы, что соединение имеет другое представление состояния базы данных по сравнению с другими рабочими процессами. Это нарушит требование согласованности данных и приведет к остановке рабочего процесса, снизив производительность СУБД. А благодаря снапшотам рабочие соединения могут просто начать новую транзакцию, установить моментальный снимок и продолжить обработку таблиц.
Кроме того, использование моментальных снимков вместо блокировок лучше масштабируется и не потребляет столько ресурсов. Блокировки требуют места в общей памяти, и при их большом количестве она может быть полностью исчерпана, что приведет к сбою резервного копирования. Вместо этого дополнительные соединения удерживают блокировку только до тех пор, пока это необходимо для обработки таблицы, а затем она освобождается. Такой подход устраняет вероятность сбоя резервного копирования на полпути из-за слишком большого количества блокировок.
Узнайте больше подробностей про администрирование и эксплуатацию Greenplum с Arenadata DB для эффективного хранения и аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники