Внедрение DDL-команд в транзакции — одна из самых полезных возможностей, предоставляемых СУБД. Однако не все базы данных умеют проводить откат DDL-изменений. Oracle, PostgreSQL, MySQL, MariaDB, DB2, MSSQL, Teradata, Greenplum, Netezza, Redshift, Aurora — это самые популярные реляционные СУБД. В этой статье мы рассмотрим их возможности по поддержке DDL-команд в транзакции.

Транзакция — это группа команд, объединённых в единую логическую единицу. Следовательно, транзакция выполняется как единое целое. При прерывании транзакции она не выполняется вовсе. Транзакции призваны обеспечивать целостность баз данных, атомарное выполнение всех команд транзакции означает сохранение ограничений целостности и невозможность оставления базы данных в промежуточном, неконсистентном состоянии.

DDL (Data Definition Language) — подмножество языка запросов SQL, предназначенное для управления структурой БД (операции с базами данных, таблицами, колонками, индексами, представлениями, хранимыми процедурами, ограничениями целостности).

Наш продукт, DataArmor Database Firewall предназначен для защиты реляционных баз данных от несанкционированного доступа и утечек данных. Для выполнения этой задачи применяется мощная система политик (правил) ограничения доступа и маскировки данных. Для того чтобы обеспечить эту функциональность, в каждый момент времени наша программа должна знать состояние метаданных базы данных. К метаданным мы относим схему базы данных и набор значений системных переменных, влияющих на результаты интерпретации и выполнения запросов. Метаданные можно получить, сделав серию запросов к серверу БД.

DataArmor также поддерживает и отслеживание инкрементальных изменений, фиксируя результаты DDL-команд, проходящих через наш продукт, работающий в режиме прокси или прослушивания (сниффера). Самое интересное начинается, когда нужно поддерживать изменение метаданных внутри транзакций. Некоторые СУБД поддерживают транзакционность команд DDL, т.е. можно произвести откат таких команд при откате транзакции. Другие же СУБД не поддерживают DDL в транзакциях, — в таких СУБД DDL-команды неявно завершают текущую транзакцию, либо вызывают ошибку SQL-сервера.

Но большинство популярных СУБД находятся где-то посередине: они поддерживают транзакционность DDL-команд, но не всех. Обычно самые глобальные команды, которые связаны с созданием или удалением объектов файловой системы в хранилище СУБД, не могут поддерживать процедуру отката, поэтому транзакционность поддерживается для более мелких команд, выполнение или откат которых не приводит к изменениям в структуре файловой системы. Транзакции во всех СУБД схожи только в общих чертах. На практике же каждая СУБД обладает уникальным синтаксисом SQL-команд управления транзакциями, и каждая имеет своё специфическое представление о том, как должны работать и управляться транзакции. Всё это мы называем «моделью транзакций» конкретной СУБД.

Для корректной обработки изменений в метаданных наша программа должна уметь откатывать те DDL-изменения, которые отменяются при откате транзакции. Это непростая алгоритмическая задача: поддержка дельты (diff) метаданных, которые соответствуют DDL-изменениям внутри текущей транзакции каждого соединения к СУБД. Такая дельта существует до завершения транзакции и может быть откачена целиком или частично — для тех СУБД, модель транзакций которых предполагает наличие многоуровневых (вложенных) транзакций или точек сохранения (save point).

Далее рассмотрим по порядку все поддерживаемые DataArmor СУБД и рассмотреть предоставляемые ими возможности с точки зрения транзакционного DDL.

1. Oracle Database

В Oracle не предусмотрена поддержка транзакционного DDL: транзакция завершается, когда выполняется команда CREATE, DROP, RENAME или ALTER. Если транзакция содержала DML-команды, то Oracle сначала делает подтверждение (commit) транзакции, а затем подтверждает DDL-команду как отдельную транзакцию.

2. PostgreSQL

PostgreSQL поддерживает транзакционный DDL: все DDL-команды, кроме «крупнокалиберных» операций создания/удаления таких объектов как DATABASE, TABLESPACE, CLUSTER. PostgreSQL поддерживает многоуровневые транзакции на уровне точек сохранения. В отличие от стандартного SQL, PostgreSQL поддерживает точки сохранения с одинаковыми именами. Более ранние точки с одинаковым именем недоступны, пока существуют более поздние.

В случае возникновения ошибки внутри транзакции, Postgres откатит всю транзакцию, но при этом он всё равно требует команды завершения (COMMIT, ROLLBACK, ABORT) текущей транзакции. PostreSQL начинает неявную транзакцию в начале multistatement и переводит транзакцию в явную, когда внутри multistatement встречается BEGIN (при этом транзакция продолжает считаться начатой с началом multistatement).

3. MySQL

MySQL не поддерживает транзакционный DDL. Для MyISAM транзакций нет как таковых. Для InnoDB DDL-команды приводят к неявному подтверждению текущей транзакции.

4. MariaDB

MariaDB унаследовала поведение в отношение транзакционного DDL от MySQL и также не поддерживает его.

5. DB2

DB2 полноценно поддерживает транзакционный DDL.

DB2 поддерживает многоуровневые транзакции как на уровне вложенных транзакций, так и точек сохранения. Точки сохранения имеют независимые пространства имён на каждом уровне вложенности.

6. Microsoft SQL Server (MS SQL)

SQL Server поддерживает транзакционный DDL.

Поддержка многоуровневых транзакций в MS SQL сводится к поддержке точек сохранения. Так называемые «вложенные» транзакции в MS SQL — всего лишь счётчик количества вызовов BEGIN TRANSACTION, и для подтверждения нужно вызвать соответствующее количество COMMIT TRANSACTION, при этом ROLLBACK откатывает всю транзакцию независимо от уровня вложенности. Началом транзакции всегда считается место первого BEGIN TRANSACTION. При этом остаётся возможность реализовать полноценную работу с многоуровневыми транзакциями посредством точек сохранения, работа с которыми выражена через команды SAVE TRANSACTION и ROLLBACK TRANSACTION <имя точки сохранения>;.

7. Teradata

Teradata не поддерживает транзакционный DDL. DDL может встречаться внутри транзакции, но не более одной команды внутри транзакции и только последней командой в транзакции. В этом смысле Teradata напоминает Oracle. Таким образом, DDL либо выполняется с завершением всей транзакции, либо — не выполняется, с откатом всей транзакции. Т.е. не существует таких DDL изменений, которые могут некоторое время существовать, а затем быть откаченными.

8. Greenplum

Greenplum полностью повторяет поведение PostgreSQL.

9. Netezza

Netezza также отпочковалась от PostgreSQL, но достаточно давно. И в ней есть некоторые заметные отличия в поддержке транзакций. Netezza также поддерживает DDL в транзакциях, но в ней нет поддержки многоуровневых транзакций (точек сохранения), а также нельзя начинать транзакцию не сначала мультистейтмента, если ранее в этом мультистейтменте есть DDL-команды.

10. Amazon Redshift

Аналогичен PostgreSQL.

11. Amazon Aurora

Аналогична MySQL в отношении DDL в транзакциях.

Все знания о приведённых выше особенностях поддержки транзакций воплощены в продукте DataArmor Database Firewall. Мы всегда знаем, как выглядит схема вашей БД и обеспечиваем её безупречную защиту.

Комментарии