聊一個數據庫腳本的版本工具 Liquibase,官網在這里 ,初次看到,挺神奇的,數據庫腳本也可以有版本管理,同類型的工具還有 flyway 。
開發過程經常會有表結構和變更,讓運維來維護的話,通常會有很大的溝通成本,有時在開發方案有問題的時候,提測失敗整個項目需要回滾,代碼回滾起來是很容易的,通常有備份,但數據庫的話就要人工來逐行分析並寫出回滾語句,Liquibase 這時候就有用了。
Liquibase 適用場景感覺不多,所以可能有人沒聽過它的名頭; 首先這種自動執行的家伙肯定是不適合於生產環境的,然后在數據量大的時候是不可能用數據庫自帶的 alter 語句的,一般都是手動創建另一張表,然后用 sql 語句將數據批量復制過去,再者使用容器化也比它好,個人覺得它一般用於開發和測試環境,比較厲害的一個功能是可以比較兩個庫的差異然后生成補丁包,上線時可以這么玩。
這篇文章 說得不錯,我是在這篇基本上寫的
核心概念
首先它是用於管理數據庫版本的,所以就會有這些概念:版本號,管理的數據,差異比較,版本回滾
它的版本號由開發人員來維護,使用 author + id
管理的數據最小單元為 changeSet ,這個 changeSet 看官網說是可以用 xml,yaml,json,sql 來編寫
提交數據,比較差異,版本回滾 可以使用命令行 或者 maven ,ant 等構建工具來完成
從命令行開始
看網上說的都是集成自 springboot ,但這種數據庫腳本一般公司都是運維在維護,使用命令行是最方便的方式,所以我先說下使用命令行,官網示例
為先為了不每次都要寫一大堆參數,可以在 liquibase 根目錄加一個 liquibase.properties,用於配置數據庫 jar 包,url ,用戶名,密碼等參數,配置詳情
命令格式: liquibase [options] [command] [command parameters]
比較開發庫和測試庫的差異,並生成升級包
如果要升級哪個,則哪個要做為源,則配置中的 url 不是 referenceUrl,使用如下命令創建升級包
liquibase --changeLogFile="changeLogFiledevtest.postgresql.sql" diffChangeLog
changeLogFile 是有命名規則的,命名必須為 *.dbType.format ,如上所示
為測試庫打一個標簽
liquibase tag v1.0
使用差異升級源庫
liquibase --changeLogFile="sqls/changeLogFiledevtest.postgresql.sql" update
升級有問題需要回滾
liquibase 有幾種回滾策略,一種是根據標簽回滾,回滾次數,和根據日期回滾;有 9 個與之對應的命令
回滾要求對應的 changeLogFile 有回滾標簽 ,這個在后面文件格式說
# 按照 changeSet 次數回滾
liquibase --changeLogFile="sqls/changeLogFiledevtest.postgresql.sql" rollbackCount 1
# 按照標簽回滾
liquibase --changeLogFile="sqls/changeLogFiledevtest.postgresql.sql" rollback v1.0
生成數據庫腳本(新環境)
liquibase --changeLogFile="sqls/create_table.mysql.sql" generateChangeLog
原理
它會在你的目標數據庫生成一張表 DATABASECHANGELOG
來管理版本 ,另一個 lock 的是防止多人同時操作數據庫加的鎖。
文件格式
其實各種文件格式使用生成數據庫腳本就可以看到格式了,照着寫就行
sql 文件格式
--liquibase formatted sql
--changeset <author>:<version>
sqls
--rollback rollback sqls
--comment: 注釋都有特殊含義了,所以注釋要這樣加
詳情見官網 sql 文件格式
XML 文件格式
xml 比 sql 更加可控,它可以加一個預判斷條件,來判斷這個后面的 changeSet 要不要執行,但相應的就必須照它的語法來寫語句了,沒 sql 方便了,還好提供了 xsd
<preConditions>
<runningAs username="liquibase"/>
</preConditions>
<!-- 版本 1 的修改-->
<changeSet id="1" author="sanri">
<addColumn tableName="person">
<column name="username" type="varchar(8)"/>
</addColumn>
</changeSet>
見官網 XML 文件格式
json 和 yaml 就不說了,更加不好控
使用構建工具
前面說了,我們也可以使用 maven 來執行這些操作,引入 maven 的一個插件就行
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<!--指定執行主文件 -->
<!-- <changeLogFile>${basedir}/src/main/resources/liquibase/master_changelog.xml</changeLogFile>-->
<!-- <diffChangeLogFile>${basedir}/src/main/resources/liquibase/changelog/${maven.build.timestamp}_changelog.xml</diffChangeLogFile>-->
<!-- <outputChangeLogFile>${basedir}/src/main/resources/liquibase/changelog/changelog_original.xml</outputChangeLogFile>-->
<propertyFile>src/main/resources/liquibase/liquibase.properties</propertyFile>
<dropFirst>false</dropFirst>
<verbose>true</verbose>
<logging>debug</logging>
<!-- 是否需要彈出確認框 -->
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
<!--輸出文件的編碼 -->
<outputFileEncoding>UTF-8</outputFileEncoding>
<!--執行的時候是否顯示詳細的參數信息 -->
<verbose>true</verbose>
<!--是否每次都重新加載properties -->
<propertyFileWillOverride>true</propertyFileWillOverride>
<rollbackTag>${project.version}</rollbackTag>
<tag>${project.version}</tag>
</configuration>
</plugin>
相應的命令做成了目標(goal),使用 -Dkey=value 來指定參數,如
# 執行更新 sql
mvn liquibase:update -DchangeLogFile="file"
# 打標簽,這個版本號在插件中配置成項目版本了
mvn liquibase:tag
# 將當前庫導出表結構
mvn liquibase:generateChangeLog
集成進 springboot ,在項目啟動的時候執行版本管理
網上都說的這種,感覺這種最不靠譜,自動執行的,萬一 sql 有個錯誤,雖然他是把每個 changeSet 做為一個事務,需要不斷的重啟項目, jenkins 每次構建很慢的,如果讓運維來手動重啟又不現實。
一點小推廣
創作不易,希望可以支持下我的開源軟件,及我的小工具,歡迎來 gitee 點星,fork ,提 bug 。
Excel 通用導入導出,支持 Excel 公式
博客地址:https://blog.csdn.net/sanri1993/article/details/100601578
gitee:https://gitee.com/sanri/sanri-excel-poi
使用模板代碼 ,從數據庫生成代碼 ,及一些項目中經常可以用到的小工具
博客地址:https://blog.csdn.net/sanri1993/article/details/98664034
gitee:https://gitee.com/sanri/sanri-tools-maven