几个app实例尝试同时迁移同一个数据库

时间:2012-10-10 16:15:37

标签: flyway

我刚开始在一个带有mysql数据库的标准spring 2.5 web应用程序中使用flyway。它已经投入生产多年,并且拥有大量数据。

我把它连接到启动时使用

进行自动迁移
<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和afaik它试图用

锁定元数据表
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

我当然可以半手动部署,如果我知道将会有长时间运行的迁移,例如只需更新一个实例并等待直到它通过迁移,然后更新其他实例。

有没有人有任何其他建议?

1 个答案:

答案 0 :(得分:1)

有三种可能性: