老板:把数据库变更,给整利索了

运维 数据库运维
经过千难万险的开发,系统终于上线了,进入了更加惊险刺激的捉虫阶段。在修修补补之中,给后人留下一堆屎山之前,我们需要把数据库给整利索了。

 [[356637]]

本文转载自微信公众号「小姐姐味道」,作者小姐姐养的狗。转载本文请联系小姐姐味道公众号。  

经过千难万险的开发,系统终于上线了,进入了更加惊险刺激的捉虫阶段。在修修补补之中,给后人留下一堆屎山之前,我们需要把数据库给整利索了。

想想吧,我们在开发环境,修改了多个字段的名称,经历了测试环境的洗礼,还搞了个预上线接受变更。结果,仅仅在线上忘了操作其中一条SQL,就前功尽弃。如果你做的是项目类型的工作,客户半年六个月才升级一次,这些脚本的管理就会乱上加乱。

我们需要把这些数据库变更,使用git这样的工具管理起来,在系统启动的时候,能够自动变更。通过口口相传,太不可信了。

谁也不想背这个锅。翻聊天记录?有用么?都是事后诸葛亮。

人和动物的区别,就是使用工具。经常被使用的两个,有Liquibase和Flyway。但是,Liquibase的迁移脚本写起来太复杂,需要花很多时间维护,远不如Flyway这样的开箱即用(牺牲跨平台)。如果你的项目不是非常复杂,对Liquibase也不熟悉,建议直接选用flyway。

一般,数据库变更,会有下面几种语句,我们都可以使用flyway来完成。

  • DDL 建表和索引的时候,用到的语句,比如CREATE、ALTER、DROP等
  • DML 就是一些常见的数据操作语句,比如update、delete、insert
  • DCL 用来设置和管理权限方面信息的语句,比如grant、deny、revoke等

下面,就以flyway为例,来看一下数据库的版本,是如何变更的。

1. flyway migrate

首先,使用mvn的命令,创建一个示范项目。

  1. mvn archetype:generate -B \ 
  2. -DarchetypeGroupId=org.apache.maven.archetypes \ 
  3.     -DarchetypeArtifactId=maven-archetype-quickstart \ 
  4.     -DarchetypeVersion=1.1 \ 
  5.     -DgroupId=foo \ 
  6.     -DartifactId=bar \ 
  7.     -Dversion=1.0-SNAPSHOT \ 
  8.     -Dpackage=foobar 

在pom.xml文件中加入下面的内容:

  1. <build> 
  2.     <plugins> 
  3.         <plugin> 
  4.             <groupId>org.flywaydb</groupId> 
  5.             <artifactId>flyway-maven-plugin</artifactId> 
  6.             <version>7.3.1</version> 
  7.             <configuration> 
  8.                 <url>jdbc:h2:file:./target/foobar</url> 
  9.                 <user>sa</user
  10.             </configuration> 
  11.             <dependencies> 
  12.                 <dependency> 
  13.                     <groupId>com.h2database</groupId> 
  14.                     <artifactId>h2</artifactId> 
  15.                     <version>1.4.200</version> 
  16.                 </dependency> 
  17.             </dependencies> 
  18.         </plugin> 
  19.     </plugins> 
  20. </build> 

创建数据库变更目录。

  1. mkdir -p src/main/resources/db/migration 

创建新的数据库文件,我们把它叫做第一个版本:src/main/resources/db/migration/V1__Create_person_table.sql

  1. create table PERSON ( 
  2.     ID int not null
  3.     NAME varchar(100) not null 
  4. ); 

使用mvn命令,即可完成数据库更新。不要怕,这个命令是幂等的。

  1. mvn flyway:migrate 

终端将输出下面的内容:

  1. [INFO] Database: jdbc:h2:file:./target/foobar (H2 1.4) 
  2. [INFO] Successfully validated 1 migration (execution time 00:00.009s) 
  3. [INFO] Creating Schema History table"PUBLIC"."flyway_schema_history" 
  4. [INFO] Current version of schema "PUBLIC": << Empty Schema >> 
  5. [INFO] Migrating schema "PUBLIC" to version 1 - Create person table 
  6. [INFO] Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.038s) 

下面,我们准备第二个变更,同样的,我们创建第二版本的文件:src/main/resources/db/migration/V2__Add_people.sql

下面是SQL文件的内容:

  1. insert into PERSON (ID, NAMEvalues (1, 'Axel'); 
  2. insert into PERSON (ID, NAMEvalues (2, 'Mr. Foo'); 
  3. insert into PERSON (ID, NAMEvalues (3, 'Ms. Bar'); 

再次执行mvn flyway:migrate,可以发现第二版本的DML信息,已经被写入到数据库。

2. 如何工作?

那flyway是如何做到幂等的呢?我们使用DBeaver来打开这个h2文件。

在JDBC连接处,输入:jdbc:h2:/private/tmp/bar/target/foobar.mv.db;然后选择H2 Embedded模式。我们发现,数据库中除了用户创建的PERSON表,还多了一个叫做flyway_schema_history的表。

让我们see一see里面的内容。使用mvn flyway:info命令,能看到相同的内容。

可以看到,这个幂等操作,其实是由一张自动创建的状态表,来保证的。里面还躺着一个叫做checksum的字段,李曼存储的是一个CRC32值,用来判断你的SQL文件是否经过了非法篡改(篡改后将不予通过)。

捅破了这层窗户纸,一切神奇的事情忽然就变得豁然开朗。所以如果你想要用flyway,你的账户,应该起码给create table的权限,否则你就需要手动建这种表。

从上面的SQL文件定义,也可以看出来,这些文件,需要遵循一定的规律。大体如上图所示,包含:

  1. 前缀
  2. 版本号
  3. 分隔符
  4. 版本描述

flyway就是靠这种约定,来进行库表变更的。所以,要严格按照它的要求去命名Sql文件。

3. SpringBoot项目集成

在pom中加入flyway的坐标。可以看到我们是没有提供版本号的,说明它已经在bom文件中定义过了。而它的autoconfigure,在SpringBoot的autoconfigure包里面默认提供了。

  1. <dependencies> 
  2.       <dependency> 
  3.          <groupId>org.flywaydb</groupId> 
  4.          <artifactId>flyway-core</artifactId> 
  5.       </dependency> 
  6.       ... 
  7. </dependencies> 

我们当然要看一下FlywayProperties这个文件所定义的配置项。可以看到它的前缀,就是spring.flyway。

默认的DB变更文件,放在classpath:db/migration,我们也可以通过locations配置自定义一个,比如classpath:cn/xjjdog/flyway。当然,也可以通过table属性,定义那张his表的名称。url、user、password这些,也可以提供,把his表存储在和业务表不一样的地方。如果不提供,将默认使用datasource所定义的库。

所以,最小配置,就是什么都不做,直接把变更文件,扔在变更目录下面就可以了。

  1. spring: 
  2.    datasource:  
  3.       # jdbc配置... 
  4. flyway: 
  5.     enable: true 
  6.     locations: classpath:cn/xjjdog/flyway 

End

一根头发一寸金,寸金难买寸光阴。

随着时间的迁移,代码和sql,都会变成屎一样的东西。如何在软件的生命中周期结束之前,让我们的工程师,活的幸福一点,才是我们该做的。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

 

责任编辑:武晓燕 来源: 小姐姐味道
相关推荐

2017-12-01 06:02:14

耦合数据库CA

2022-03-04 14:57:50

缓存数据库代码

2024-05-14 08:20:59

线程CPU场景

2022-07-30 12:24:55

智能围巾传感器心率

2021-02-01 09:04:42

Python 项目distutils

2020-10-26 07:02:11

ConcurrentH存储

2011-08-25 13:41:50

SQL Server 变更跟踪

2020-07-27 08:26:03

数据库 SQL索引

2019-09-27 09:13:55

Redis内存机制

2021-11-07 21:01:52

云计算数据库分布式

2021-04-30 08:21:22

Linux管道设计

2010-08-10 09:37:29

DB2 9.7

2019-09-22 21:34:59

数据库平滑变更表结构

2011-03-23 17:10:41

ACCESSSQL数据库

2014-02-27 10:08:33

NoSQL

2018-12-20 09:52:05

JVM内存分配

2020-12-09 08:27:48

并发编程编程开发

2020-12-09 15:00:08

编程IT线程

2020-03-09 09:13:40

HTTPSTCP网络协议

2021-06-04 09:00:00

数据库集成工具
点赞
收藏

51CTO技术栈公众号