在星云私有化部署落地方案中,SQL版本维护是一个关键环节。我们选择了Flyway这一开源工具来实现SQL版本管理。本文将详细介绍我们如何基于Flyway进行SQL版本管理,以及如何通过这一工具解决私有化部署中的SQL管理难题。
背景
在私有化部署过程中,我们面临了两个主要的SQL管理挑战:
1. 初始化SQL的不确定性:随着日常迭代的推进,私有化部署的初始化SQL无法固定。每次搭建私有化环境时,都需要从当前库中导出表结构,并分析哪些数据需要在初始化阶段写入。
2. 私有化升级的复杂性:由于缺乏SQL版本管理,我们无法准确知道客户版本与升级版本之间的差异。只能通过人工排查问题并补充SQL,这种方式不仅工作量大,还容易遗漏,导致系统问题频发。
为了解决这些问题,我们需要一个能够像Git管理代码一样管理SQL的工具,能够自动执行后续版本的SQL,并记录执行状态。经过调研,我们选择了Flyway,它能够高效地管理SQL版本,并自动执行指定版本之后的SQL。
使用方法
第一步:引入Flyway。
Spring Boot已经集成了Flyway,只需引入Flyway的依赖包即可激活FlywayAutoConfiguration。我们在common包中引入Flyway依赖,无需指定版本,使用与当前Spring Boot配套的版本即可。
<dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> </dependency>
第二步:配置Flyway。
在通用的配置文件中(如application-dev.yaml),增加Flyway的配置:
spring: flyway: locations: - classpath:/sql/prod/ddl #存放每次迭代开发的SQL文件目录 table: t_flyway_history #flyway存放SQL执行版本的表,该表不存在的时候会自动创建 checkLocation: false #flyway在执行的时候检查SQL文件目录是否存在,默认值是true,这里改成false,为了避免有些服务没有SQL导致服务启动失败 baselineOnMigrate: true #对于不是空的数据库flyway,该值必须设置为true,用于告诉flyway此次执行的库是基于非空的库进行的 validateOnMigrate: true #设置flyway在真正执行脚本之前是否对已经执行过的SQL脚本文件进行校验,如果发现已经执行过的文件发生了变动则会失败 baselineVersion: 2.9.7 #设置最开始从哪个版本开始执行,注意是大于该版本。 installedBy: flyway #指定这次SQL执行者的名字 cleanDisabled: true #是否禁用clean功能,这里一定要设置为true,就是将clean功能禁用掉,因为一旦谁执行了clean功能会把数据库清空。 validateMigrationNaming: true #是否验证SQL文件的名字是否符合规范
第三步:维护SQL文件。
SQL文件的目录结构如下图所示:
-
dev目录:存放开发阶段的SQL文件,方便后续整理和上线。文件名应以上线版本命名,如V2.9.7__***。
-
prod目录:存放测试、UAT和生产环境的SQL文件。ddl目录存放新环境搭建时需要执行的SQL,migration目录存放数据迁移脚本。
Flyway管理的SQL文件必须符合命名规范,如V2.9.7__***,并支持小版本号,如V2.9.7.1。
第四步:SQL编写规范。
为了确保Flyway能够正常执行SQL,我们需要遵循以下规范:
1. SQL可重复执行:确保SQL脚本可以多次执行而不出错。
2. 避免事务控制关键字:不要在SQL中使用BEGIN、COMMIT等关键字。
3. 以分号结束:每条SQL语句必须以分号结束。
4. 判断SQL是否放入ddl:如果SQL在新环境搭建或升级时需要执行,则应放入ddl目录。
5. 使用占位符:对于随环境变化的值,使用Flyway的占位符功能。例如:
INSERT IGNORE INTO `oauth_client_details` VALUES ('${oauth_client_id_nebula}', NULL, '${oauth_client_secret_nebula}', '${oauth_client_scope_nebula}', 'we_chat,sms_code,password,authorization_code,refresh_token', NULL, NULL, 7200, 7500, NULL, 1, NULL);
另外需要在配置文件中配置占位符的值:
spring: flyway: placeholders: oauth_client_id_nebula: nebula oauth_client_secret_nebula: aaddaeeadfafd oauth_client_scope_nebula: webapp
这里的${oauth_client_id_nebula}、${oauth_client_secret_nebula}和${oauth_client_scope_nebula}就是变量占位符,特别注意:上面的SQL语句中一定要在占位符外面加上单引号,这里的占位符就是对等替换。
第五步:Flyway工具扩展
如果需要对Flyway进行扩展,可以在工具包中编写扩展程序。例如,我们实现了一个FlywayCustomizedConfiguration类,用于在SQL执行前进行修复操作,确保失败后可以直接修改并重新执行,而无需创建新的版本。
Flyway执行过程
Flyway在服务启动时执行指定目录下的SQL,具体步骤如下:
1. 连接数据库:连接服务所配置的数据库。
2. 查询版本历史:查询t_flyway_history表,获取当前版本。
3. 校验SQL文件:检查sql/prod/ddl目录下的SQL文件,确保已执行的SQL文件未被修改。
4. 执行SQL:执行大于当前版本的所有SQL文件。
备注:如果执行失败,可以直接修改SQL文件并重新执行,无需创建新版本。不支持跳版本执行,确保版本递增,避免不兼容问题。
总结
本文详细介绍了我们如何通过Flyway解决私有化部署中的SQL版本管理难题。通过引入Flyway、配置SQL文件目录、制定SQL编写规范以及扩展Flyway功能,我们大大提升了私有化部署的效率。Flyway不仅简化了SQL版本管理,还确保了数据库的一致性和可维护性。如果您对Flyway的更多功能感兴趣,建议参考官方文档。