3

mysqlデータベースを使用したかなり標準的なSpring2.5Webアプリケーションでflywayを使い始めたところです。それは何年もの間生産されており、たくさんのデータを持っています。

起動時に自動移行するように接続しました

<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
    <property name="dataSource" ref="dataSource"/>
</bean>

また、Springの永続性ユニットマネージャー(jpaを使用)がそれに依存するようにしたため、JPAが初期化される前にデータベースが移行されます。

これは正常に機能します。

実稼働環境には、同時に更新したいノードがいくつかあります。したがって、実行時間が長い場合、各インスタンスは同じ移行を実行しようとします。Flywayのロック機能はそれを防ぐはずです。

私は本番環境で何かをする前にこれらのことをテストするのが好きなので、そうしました。また、2つのアプリインスタンスが長時間の移行(6分)で同時に開始されたときに何が起こったのかというと、しばらくすると2番目のインスタンスが次のように失敗しました。

 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つのインスタンスを更新し、移行が通過するまで待ってから他のインスタンスを更新するなど、長時間実行される移行が発生することがわかっている場合は、半手動でデプロイを行うことができます。

他に何か提案はありますか?

4

1 に答える 1

1

3つの可能性があります:

  • 実行時にinnodb_lock_wait_timeoutを設定できるMySQL5.5に移動します
  • サーバー構成でグローバルinnodb_lock_wait_timeoutを増やします
  • タイムアウトを超えないように移行を分割します
于 2012-10-11T12:14:58.780 に答える