Я только начал использовать flyway в довольно стандартном веб-приложении Spring 2.5 с базой данных mysql. Он был в производстве в течение многих лет и имеет много данных.
Я подключил его для автоматической миграции при запуске с помощью
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
<property name="dataSource" ref="dataSource"/>
</bean>
и сделал так, чтобы диспетчер единиц персистентности Spring (с использованием jpa) зависел от него, поэтому база данных будет перенесена до инициализации JPA.
Это прекрасно работает.
В нашей производственной среде у нас есть несколько узлов, которые мы хотели бы обновлять одновременно. Таким образом, каждый экземпляр будет пытаться выполнить одни и те же миграции, если они выполняются долго. Функциональность блокировки Flyway должна предотвратить это.
Мне нравится тестировать эти вещи, прежде чем что-то делать в продакшене, что я и сделал; и что произошло, когда два экземпляра приложения запускались одновременно с длительной миграцией (6 минут), так это то, что через некоторое время второй экземпляр вышел из строя с:
Caused by: com.googlecode.flyway.core.exception.FlywayException: Unable to lock metadata table 'schema_version' in schema 'dbschema'
at com.googlecode.flyway.core.metadatatable.MetaDataTable.lock(MetaDataTable.java:148)
at com.googlecode.flyway.core.migration.DbMigrator$1.doInTransaction(DbMigrator.java:116)
at com.googlecode.flyway.core.migration.DbMigrator$1.doInTransaction(DbMigrator.java:114)
at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:54)
at com.googlecode.flyway.core.migration.DbMigrator.migrate(DbMigrator.java:113)
...
Глубже в трассировке стека находится SQLException:
Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
...
По существу, кажется, тайм-аут.
Мы используем mysql и, на самом деле, пытаемся заблокировать таблицу метаданных с помощью
select * from dbschema.schema_version for update
Я проверил базу данных, которую он пытался перенести, и тайм-аут ожидания блокировки:
mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 120 |
+--------------------------+-------+
Который явный виновник. Однако я не уверен, что хочу увеличить сумму, так как я мог бы захотеть, чтобы она истекла, если такое событие произойдет по какой-то другой причине.
Я мог бы попытаться установить более высокое значение на время миграции. За исключением того, что это, кажется, переменная только для чтения:
SET innodb_lock_wait_timeout = 240;
ERROR 1238 (HY000): Variable 'innodb_lock_wait_timeout' is a read only variable
Я мог бы, конечно, выполнить развертывание в полуручном режиме, если я знаю, что будут длительные миграции, например. просто обновите один экземпляр и подождите, пока он не пройдет миграцию, а затем обновите другие экземпляры.
У кого-нибудь есть другие предложения?