【学无止境】DB Migration Tool - Flyway 实战
问题
观察现有的开发和上线流程,发现自动化的程度不高。其中一个典型的例子就是DB脚本的执行,是由人手动一个个文件跑的。
这样做有两个主要的问题:
- 效率低,耗时。这一步往往要做半小时甚至更久。
- 容易出错,比如漏掉某个脚本。
- 无法重复执行。比如上午组员A刚把某文件夹下的所有脚本都跑完一遍,下午B,C又有提交,组员A还得去单独找到B,C的新提交,再一个个地执行。
解决
使用DB Migration Tool:Flyway
可以解决这个问题。
Flyway是一个数据库脚本记录框架。可以记录所有脚本执行的情况。有了这个记录,我们可以知道那些脚本跑过了,哪些还没有跑,从而实现数据库同步。
原理
- 运行Flyway,它会扫描指定文件夹下的所有的脚本,并依次执行。
- 它会将执行记录保存到数据库中。默认表名为:
flyway_schema_history
。 - 当下次执行时,根据
flyway_schema_history
,它会跳过已经执行过的脚本,只跑新的脚本。
校验和 - Checksum
flyway_schema_history
的表大概是这个样子:
有两栏特别说明下:
- checksum:可以配置该功能,使得Flyway能根据文件的checksum值判断是否为新文件,需不需要再次执行。
- success:一般来说,如果是error的话,会重新运行该脚本。但是,如果手动fix了之后,可以考虑是否需要在
flyway_schema_history
中把这个flag改掉,从而避免重复执行。
Checksums and Validation of Flyway
另外,关于重复执行DB脚本不出错,Flyway和可重复执行SQL理论上是二选一即可。
事务 - Transaction
Flyway的事务默认是文件级别的。即一个个文件依次执行,ABC成功了,D失败了,则只回滚D,ABC不受影响。
当然,这个可以配置,比如我希望把ABCD当作一个事务,也是可以实现的,把他们都放在一个目录下,且set the group
property to true
。
另外,对于回滚操作,不同数据库支持的程度不一样。有的数据库(比如PostgreSQL, Aurora PostgreSQL, SQL Server and SQLite)支持回滚transactional statements
and non-transactional statements
。
有些则不支持。这也很好理解,你在Oracle里面建了一个新的table,然后点rollback按钮,是无效的。
使用 - Dependency
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.0.7</version>
</dependency>
使用 - Code
Flyway flyway = new Flyway();
flyway.setTable("VERSION_TABLE");
flyway.setBaselineOnMigrate(false);
flyway.setValidateOnMigrate(true);
flyway.setDataSource(jdbcUrl, schema, password);
flyway.setSchemas(schema);
flyway.setSqlMigrationPrefix("NV");
flyway.setRepeatableSqlMigrationPrefix("RV");
flyway.setLocations("filesystem:" + sqlDir);
flyway.migrate();