Running multiple mysql statements in one transacti

2019-04-14 23:25发布

问题:

I'm using the Mybatis migration tool to maintain the schema to our database but I'm having the following problem.

Currently, if we use multiple statements in a migration they are each run in a separate transaction. So if I want to alter 2 tables (or run multiple statements) as part of a feature and one of them breaks, any that were run first have to be manually reverted. The mybatis migration however is only marked as complete in the changelog table if all statements completed successfully.

This is really frustrating because there's no way to maintain a constant db state if the entire migration isn't autonomous.

Settings

here's the (relevant) setting for mybatis mygration for our test database.

## 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

I've added auto_commit=false, send_full_script=true and allowMultiQueries=true (to url) in an attempt to keep the whole migration in one transaction.

Are there any mysql url parameters that I need to use to allow this? Is this even possible? Seems like it should be. Maybe we just need to create one migration for each statement but that seems excessive.

Example

Here's a further example for clarification

Example migration 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 ....

If I run migrate up it fails because of the b0rked; line as expected. migrate status shows the migration as pending as expected.

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

my database however has the changes applied! not good!

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)

Is there any way to prevent this? Should I just put each statement in a migration and move on? that's where I am right now.

Thanks in advance.

回答1:

DML is never transactional -- applied immediately. There is no way to roll it back