Запуск нескольких операторов mysql в одной транзакции в инструменте миграции Mybatis

Я использую инструмент миграции Mybatis для сохранения схемы в нашей базе данных, но у меня возникла следующая проблема.

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

Это действительно расстраивает, потому что невозможно поддерживать постоянное состояние базы данных, если вся миграция не является автономной.

Настройки

вот (соответствующая) настройка mybatis mygration для нашей тестовой базы данных.

## JDBC connection properties.
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/gamealert_test?allowMultiQueries=true
username=gamealert
password=********

# If set to true, each statement is isolated
# in its own transaction.  Otherwise the entire
# script is executed in one transaction.
auto_commit=false

# This controls how statements are delimited.
# By default statements are delimited by an
# end of line semicolon.  Some databases may
# (e.g. MS SQL Server) may require a full line
# delimiter such as GO.
delimiter=;
full_line_delimiter=false

# This ignores the line delimiters and
# simply sends the entire script at once.
# Use with JDBC drivers that can accept large
# blocks of delimited text at once.
send_full_script=true

Я добавил auto_commit=false, send_full_script=true и allowMultiQueries=true (к URL-адресу), пытаясь сохранить всю миграцию в одной транзакции.

Есть ли какие-либо параметры URL-адреса mysql, которые мне нужно использовать, чтобы разрешить это? Это вообще возможно? Кажется, так и должно быть. Возможно, нам просто нужно создать одну миграцию для каждого оператора, но это кажется чрезмерным.

Пример

Вот еще один пример для пояснения

Пример миграции 20110318154857_fix_daily_sales:

--// fix daily_sales naming
-- Migration SQL that makes the change goes here.

ALTER TABLE `daily_sales` CHANGE COLUMN `storeId` `store_id` INT(10) UNSIGNED NOT NULL;

b0rked;

--//@UNDO
-- SQL to undo the change goes here.
... undo sql here ....

Если я запускаю миграцию вверх, она не работает из-за строки b0rked;, как и ожидалось. Статус миграции показывает, что миграция находится в ожидании, как и ожидалось.

20110318130407 2011-03-18 17:06:24 create changelog
20110318144341 2011-03-18 17:06:30 fix schedule naming
20110318154857    ...pending...    fix daily sales naming

однако в моей базе данных применены изменения! нехорошо!

describe daily_sales;
+-----------+------------------+------+-----+---------+-------+
| Field     | Type             | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| store_id  | int(10) unsigned | NO   | PRI | NULL    |       |
| sale_date | date             | NO   | PRI | NULL    |       |
| type_id   | int(10) unsigned | NO   | PRI | NULL    |       |
| tokens    | int(10) unsigned | NO   |     | 0       |       |
| dollars   | double           | NO   |     | 0       |       |
+-----------+------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

Есть ли способ предотвратить это? Должен ли я просто поместить каждый оператор в миграцию и двигаться дальше? вот где я сейчас.

Заранее спасибо.


person Dave    schedule 21.03.2011    source источник


Ответы (1)


DML никогда не является транзакционным — применяется немедленно. Нет возможности откатить его назад

person Nick Rapoport    schedule 25.03.2011
comment
Спасибо. Вот что я понял. Итак, на данный момент решение моей проблемы состоит в том, чтобы иметь не более одного оператора для каждого сценария миграции. - person Dave; 25.03.2011
comment
не совсем верно. некоторые поставщики баз данных позволяют фиксировать или откатывать операции DDL как атомарные операции. - person alberto sarubbi; 24.05.2011
comment
Да, спасибо за комментарий. Мой пример был для MySQL, поэтому ответ правильный для MySQL, но вы также правы. Я использую PostgreSQL в другом проекте, и большинство операций DDL являются транзакционными. - person Dave; 24.05.2011