持續交付項目中,項目會不斷的迭代上線,這是會出現數據庫的改動問題。在一個還未上線的項目中,我更改數據庫可以使用簡單的直接對sql進行更改,但是面對一個已投入使用的系統而言,每次部署都對數據庫進行init顯得有點不太可能。於是便有了數據庫Migration的誕生。
我所在的項目是SpringMVC配合Mybatis的開發框架。作爲一個數據庫集成框架,Mybatis在使用上還是比較方便的。言歸正傳,爲了項目需要,於是便開始了Mybatis Migration的初探,文章中出現的不妥之處還請大家不吝賜教。
Mybatis Migration 安裝
安裝過程主要參照Mybatis的官網: http://mybatis.github.io/migrations/index.html,以及Mybatis源代碼授權地址: https://github.com/mybatis/migrations,參照github上的README文件可以輕易的完成其安裝過程。README文件中所有的Mybatis包可以直接在其Git repo的releases中找到,我選擇了3.2.0進行下載安裝。安裝完成後就可以直接在terminal中運行migrate相關的命令了。
Mybatus Migration 初始化
minggong:migration-test minggong$ migrate init
------------------------------------------------------------------------
-- MyBatis Migrations - init
------------------------------------------------------------------------
Initializing: .
Creating: environments
Creating: scripts
Creating: drivers
Creating: README
Creating: development.properties
Creating: bootstrap.sql
Creating: 20140817132704_create_changelog.sql
Creating: 20140817132705_first_migration.sql
Done!
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 2s
-- Finished at: Sun Aug 17 18:57:05 GMT+05:30 2014
-- Final Memory: 3M/493M
------------------------------------------------------------------------
minggong:migration-test minggong$ ls
README drivers environments scripts
初始化之後的目錄下面會自動生成一些和Migration相關的項目文件及目錄 README, drivers, environments, scripts。drivers中放置連接數據庫需要的jdbc,environments主要放置連接數據庫的地址以及授權信息等,scripts目錄下則放置數據庫相關的sql,init的時候就已經生成了上述顯示的create_changelog.sql和first_migration.sql文件。
爲了以實例說明問題,本次測試採用了mysql數據庫,從mysql官網下載了mysql-connector-java-5.1.32
,並對environment的數據庫信息進行了簡單的配置,配置如下:
## JDBC connection properties.
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/arctic
username=root
password=
這裏的arctic是已經存在本地的一個mysql數據庫。
Migrate bootstrap
minggong:migration-test minggong$ migrate bootstrap
------------------------------------------------------------------------
-- MyBatis Migrations - bootstrap
------------------------------------------------------------------------
========== Applying: bootstrap.sql =============================================
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 19:43:29 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
運行之後,scripts文件中將會生成另外一個bootstrap文件。主要可以進行一些數據庫初始化工作。
Migrate new
new
命令能夠創建新的sql腳本,我們只需要填充數據表結構信息,便可以方便的創建我們所需的數據表
minggong:migration-test minggong$ migrate new "create blog table"
------------------------------------------------------------------------
-- MyBatis Migrations - new
------------------------------------------------------------------------
Creating: 20140817142201_create_blog_table.sql
Done!
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 1s
-- Finished at: Sun Aug 17 19:52:01 GMT+05:30 2014
-- Final Memory: 3M/493M
------------------------------------------------------------------------
scripts文件夾中會創建帶有時間戳的sql文件:20140817142201_create_blog_table.sql
, 其內容如下:
-- // create blog table
-- Migration SQL that makes the change goes here.
-- //@UNDO
-- SQL to undo the change goes here.
文件內容主要包含create table
和undo
,分別表示表的創建和刪除命令:
-- // create blog table
-- Migration SQL that makes the change goes here.
CREATE TABLE BLOG (
ID INT,
NAME VARCHAR(255),
PRIMARY KEY(ID)
);
-- //@UNDO
-- SQL to undo the change goes here.
DROP TABLE BLOG;
已經將表結構寫在了sql裏面,那麼怎樣執行這個腳本,從而改變數據庫中的表結構呢。首先我們需要了解當前數據庫的狀態。
Migrate status
minggong:migration-test minggong$ migrate status
------------------------------------------------------------------------
-- MyBatis Migrations - status
------------------------------------------------------------------------
ID Applied At Description
================================================================================
20140817132704 ...pending... create changelog
20140817132705 ...pending... first migration
20140817142201 ...pending... create blog table
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 20:21:06 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
由於我們沒有運行過migration, 所以所有migration腳本都處於pending
狀態,包括changelog table本身。當我們運行migrate up
命令之後,腳本的狀態便會發生相應的改變。
Migrate up, down
爲了顯示更多up, down以及後續的version操作,再次新建一個數據表migrate new 'create table author'
此時的author和blog應該都處於pending狀態。
minggong:migration-test minggong$ migrate status
------------------------------------------------------------------------
-- MyBatis Migrations - status
------------------------------------------------------------------------
ID Applied At Description
================================================================================
20140817132704 ...pending... create changelog
20140817132705 ...pending... first migration
20140817142201 ...pending... create blog table
20140817154537 ...pending... create table author
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 21:21:49 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
minggong:migration-test minggong$ migrate up
------------------------------------------------------------------------
-- MyBatis Migrations - up
------------------------------------------------------------------------
========== Applying: 20140817132704_create_changelog.sql =======================
-- Create Changelog
-- Default DDL for changelog table that will keep
-- a record of the migrations that have been run.
-- You can modify this to suit your database before
-- running your first migration.
-- Be sure that ID and DESCRIPTION fields exist in
-- BigInteger and String compatible fields respectively.
CREATE TABLE CHANGELOG (
ID NUMERIC(20,0) NOT NULL,
APPLIED_AT VARCHAR(25) NOT NULL,
DESCRIPTION VARCHAR(255) NOT NULL
)
ALTER TABLE CHANGELOG
ADD CONSTRAINT PK_CHANGELOG
PRIMARY KEY (id)
========== Applying: 20140817132705_first_migration.sql ========================
-- First migration.
-- Migration SQL that makes the change goes here.
========== Applying: 20140817142201_create_blog_table.sql ======================
-- create blog table
-- Migration SQL that makes the change goes here.
========== Applying: 20140817154537_create_table_author.sql ====================
-- create table author
-- Migration SQL that makes the change goes here.
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 21:22:17 GMT+05:30 2014
-- Final Memory: 13M/493M
------------------------------------------------------------------------
migrate up
命令會將所有的sql進行up,所有處於pending狀態的SQL腳本都會進行執行。對應的migrate down
則是undo sql腳本的執行,也就是執行sql中用戶自定義的UNDO部分。不同的是migrate down
只能回退一步,所以回退到初始狀態則需要運行多次的migrate down
操作。當然也可以直接指定參數,本例中我們指定回退4步migrate down 4
:
minggong:migration-test minggong$ migrate status
————————————————————————
– MyBatis Migrations - status
————————————————————————
ID Applied At Description
================================================================================
20140817132704 2014-08-17 21:22:17 create changelog
20140817132705 2014-08-17 21:22:17 first migration
20140817142201 2014-08-17 21:22:17 create blog table
20140817154537 2014-08-17 21:26:01 create table author
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 21:26:07 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
minggong:migration-test minggong$ migrate down 4
------------------------------------------------------------------------
-- MyBatis Migrations - down
------------------------------------------------------------------------
========== Undoing: 20140817154537_create_table_author.sql =====================
-- @UNDO
-- SQL to undo the change goes here.
========== Undoing: 20140817142201_create_blog_table.sql =======================
-- @UNDO
-- SQL to undo the change goes here.
========== Undoing: 20140817132705_first_migration.sql =========================
-- @UNDO
-- SQL to undo the change goes here.
========== Undoing: 20140817132704_create_changelog.sql ========================
-- @UNDO
DROP TABLE CHANGELOG
Changelog doesn't exist. No further migrations will be undone (normal for the last migration).
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 21:29:53 GMT+05:30 2014
-- Final Memory: 14M/493M
------------------------------------------------------------------------
minggong:migration-test minggong$ migrate status
------------------------------------------------------------------------
-- MyBatis Migrations - status
------------------------------------------------------------------------
ID Applied At Description
================================================================================
20140817132704 ...pending... create changelog
20140817132705 ...pending... first migration
20140817142201 ...pending... create blog table
20140817154537 ...pending... create table author
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 21:30:09 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
Migrate verison
回滾到指定的version狀態,後面需要加上version的ID: migrate verison 20140817132705
minggong:migration-test minggong$ migrate status
------------------------------------------------------------------------
-- MyBatis Migrations - status
------------------------------------------------------------------------
ID Applied At Description
================================================================================
20140817132704 2014-08-17 22:23:05 create changelog
20140817132705 2014-08-17 22:23:25 first migration
20140817142201 2014-08-17 22:23:25 create blog table
20140817154537 2014-08-17 22:23:25 create table author
20140817164341 2014-08-17 22:23:25 create table book
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 22:23:36 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
minggong:migration-test minggong$ migrate version 20140817142201
------------------------------------------------------------------------
-- MyBatis Migrations - version
------------------------------------------------------------------------
Downgrading to: 20140817142201
========== Undoing: 20140817164341_create_table_book.sql =======================
-- @UNDO
-- SQL to undo the change goes here.
========== Undoing: 20140817154537_create_table_author.sql =====================
-- @UNDO
-- SQL to undo the change goes here.
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 22:23:43 GMT+05:30 2014
-- Final Memory: 13M/493M
------------------------------------------------------------------------
minggong:migration-test minggong$ migrate status
------------------------------------------------------------------------
-- MyBatis Migrations - status
------------------------------------------------------------------------
ID Applied At Description
================================================================================
20140817132704 2014-08-17 22:23:05 create changelog
20140817132705 2014-08-17 22:23:25 first migration
20140817142201 2014-08-17 22:23:25 create blog table
20140817154537 ...pending... create table author
20140817164341 ...pending... create table book
------------------------------------------------------------------------
-- MyBatis Migrations SUCCESS
-- Total time: 0s
-- Finished at: Sun Aug 17 22:23:47 GMT+05:30 2014
-- Final Memory: 11M/493M
------------------------------------------------------------------------
Migrate pending
migrate up
命令只能向上upgrade,而在多人合作中如果migration sql腳本先創建但是後提交,同步到一臺服務器上就有可能出現中間某個文件處於pending
狀態,這時使用migrate up
是不能使其執行的。
這種情況如果這個sql基本和其他sql無依賴時,可以直接使用migrate up
使處於pending狀態的腳本被執行。官方解釋這是不推薦的做法。另外一種做法是使用migrate version [ID]
回到pending版本之前的狀態,然後再次執行migrate up
,從而完成整個執行操作,這種做法是推薦的比較安全的。
Migrate script
使用方法爲migrate script <V1> <V2> > file.sql
migrate 20140817142201 20140817164341 > do.sql
這個do腳本的執行將會應用上述兩個狀態的執行author和book。
migrate 20140817164341 20140817142201 > undo.sql
這個將undo腳本執行可以回滾V1和V2之間的即上述狀態。
如果要在首尾之間回滾,則可以用 0 代替原始版本ID
migrate 0 20140817164341 > do.sql
migrate 20140817164341 0 > undo.sql
但是對於上述的script腳本直接使用 migrate do.sql執行卻一直報錯!官方也沒有對單個的腳本執行有說明。後續弄清楚了再補充上來。