前言
很多初学者在刚刚接触Flyway时,会习惯于直接修改原脚本,这样往往会带来一些问题;同时在多人协作中,也会遇到一些脚本执行时带来的冲突而不清楚原因所在。这类问题往往是由于不清楚flyway脚本的执行机制带来的。下面我就来分析一些这两类常见的问题以及解决方法。
正文
前置知识:Flyway执行的步骤
每个sql脚本文件都有独一无二的版本号,flyway会将所有的sql脚本文件根据版本号进行排序,然后按顺序遍历脚本文件去schema_history表找到对应版本:
- 如果未找到对应版本,则执行这个版本脚本
- 如果找到对应版本,对比checksum:
- 如果checksum相同说明执行成功了,则这个版本脚本不再被执行;
- 如果不相同说明这个文件被更改了,会报错;
- 初始化时(baseline)checksum为null,这时候没法对比,就默认已经执行成功了,所以对应版本的脚本文件不会再执行,需要更改成更高版本这个脚本才会执行
一、如果想要修改已经正确执行的脚本
如果想要修改已经正确执行的脚本,在实际项目中不推荐直接手动删除scheme_history中此脚本执行记录并修改脚本重新执行,因为手动修改的话那么再次启动程序的时候这些修改的脚本将会被最后执行,就不会按照原定的版本执行顺序去执行,可能会报错。
例如:
版本1脚本有如下sql语句:
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
column3 datatype
);
版本2脚本有如下sql语句:
ALTER TABLE table_name
ADD column4 datatype;
版本3脚本有如下sql语句:
INSERT INTO table_name (column1, column2, column3, column4)
VALUES (value1, value2, value3, value4);
如果此时删掉schema_history相应记录,修改版本2脚本:
ALTER TABLE table_name
ADD column4 datatype;
ALTER TABLE table_name
ADD UNIQUE(column4);
当修改完之后重新执行程序时,由于版本1和3脚本都已被执行,这回只会执行版本2脚本,这时由于表中已经存在column4了,这时执行脚本2会导致重复column4的重复添加,会报错。
解决方法:
所以,如果想要修改已经执行正确的脚本,还是推荐直接创建一个最新版本的脚本(这里是脚本4)作为补丁。
ALTER TABLE table_name
ADD UNIQUE(column4);
这样,当重新启动程序时,脚本2中的内容自然不会再次被执行,只有脚本4被执行,这回就不会报错,schema_history表中的执行记录显示的执行顺序也会与版本顺序相符。
二、解决多人协作冲突
当拉取他人创建的脚本不是最新版本的脚本时,要注意他人写的脚本会不会与自己写的脚本产生冲突,如果有产生冲突的可能,那么可以改变相应脚本文件的脚本号来决定脚本执行顺序。
例如:
本地的版本1脚本如下:
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
column3 datatype
);
本地版本2脚本如下:
INSERT INTO table_name (column1, column2, column3)
VALUES (value1, value2, value3);
远端拉取的脚本位于本地的两个版本之间,为版本1.5:
ALTER TABLE table_name
DROP column3;
那么当拉取下来远端代码之后,本地会出现版本1.5脚本,虽然当重新执行程序时不会报错,因为此时只会执行脚本1.5,但是当按顺序重新执行所有版本时会报错,因为不能向已经不存在的column3插入数据。脚本1.5本意是需要在脚本2之后执行的。
解决方法:
这种情况下,可以在拉取代码之后检查可能出现的脚本冲突,然后可以将版本1.5脚本的版本名改为最新版本,比如版本3,这样这个脚本就可以在本地最后执行,不会产生冲突。