【问题标题】:Several app instances trying to migrate the same database at the same time多个应用实例尝试同时迁移同一个数据库
【发布时间】:2012-10-01 04:38:28
【问题描述】:

我刚开始在一个带有 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

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

还有人有其他建议吗?

【问题讨论】:

    标签: flyway


    【解决方案1】:

    有3种可能:

    【讨论】:

    • Flyway 似乎在调用任何迁移脚本之前锁定了数据库。除非 MetaDataTable#lock() 支持将超时作为参数传递,否则在运行时设置全局锁定等待超时是不可能的吗?集群中的所有其他实例都将尝试调用 metaDataTable#lock(),但总是会在服务器的全局超时设置(50 秒)时超时。
    猜你喜欢
    • 2014-01-29
    • 2012-10-16
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    相关资源
    最近更新 更多