0%

golang-migrate初次使用


1 Install migrate CLI

直接 Release Downloads 下载对应版本。也可以安装官网说明下载。

  • Windows:下载压缩包,解压后,将 migrate.exe 放入 $GOPATH/bin 目录下

2 postgres测试

测试环境

  • windows 10
  • windows 10 下的 postgres:14.2
  • 虚拟机:vagrant + virbox + centos
1
Linux localhost.localdomain 3.10.0-1127.el7.x86_64 #1 SMP Tue Mar 31 23:36:51 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
  • docker:20.10.7

2.1 拉取 postgres 镜像

1
docker pull postgres:14-alpine

2.2 启动 docker / windows 上的 postgres 数据库

连接名:postgres ,密码:password,虚拟机地址:192.168.33.10

启动镜像

1
docker run --name postgres -e POSTGRES_PASSWORD=password -d postgres:14-alpine

进入 postgres 容器

1
docker exec -it postgres psql -U postgres

创建数据库 example

1
create database example;

\list 查看所有数据库

  • windows 略

2.3 创建某次数据库变更的 sql 文件

1
mkdir migrations #首次执行,用于存放变更的 sql 文件

比如说这次修改我们需要新增一个 users 的表,

1
migrate create -ext sql -dir ./migrations -seq create_users_table

这个命令会在 migrations 目录下生成两个文件

  • 000001_create_users_table.up.sql000001_create_users_table.down.sql , 000001 是某次修改的版本号.
  • 000001_create_users_table.up.sql 用来存放创建 users 表的 sql 脚本,
  • 000001_create_users_table.down.sql 用来存放回滚这次操作的 sql 脚本。
  • migrate create 命令只负责创建文件,sql 文件的内容需要我们手动编辑。

编辑 000001_create_users_table.up.sql

1
2
3
4
5
6
CREATE TABLE IF NOT EXISTS users(
user_id serial PRIMARY KEY,
username VARCHAR (50) UNIQUE NOT NULL,
password VARCHAR (50) NOT NULL,
email VARCHAR (300) UNIQUE NOT NULL
);

编辑 000001_create_users_table.down.sql

1
DROP TABLE IF EXISTS users;

2.4 up 与 down

  • migrate 的 up 子命令用来应用某一次数据库变更, down 子命令用来回滚数据库变更操作。
1
2
3
up [N]       Apply all or N up migrations
down [N] [-all] Apply all or N down migrations
Use -all to apply all down migrations

首次执行 migrate up 命令后,会在数据库中添加 schema_migrations 表。这个表有两个字段 version 和 dirty。

version 用来表示当前数据库对应 ./migrations 下面的那个版本,比如第一次执行 migrate up 1 后,如果执行成功了, schema_migrations 表中的 version=1,说明当前数据库对应的是 000001_create_users_table.up.sql 这个版本

dirty=false,执行到 version=1 这次的变更没有出错。如果 dirty=true ,变更出错,需手动处理。

  • up 和 down 后面的 [N] 是数量。migrate create -ext sql 命令创建 sql 文件,并给其标号。up 的执行顺序是从小到大,down 是从大到小。up 和 down 执行文件的起始标号根据schema_migrations 里面的 version 确定。若schema_migrations 为空表或不存在,则可认为 version 为 0 。up 的起始标号为 version + 1。 down 为 version

    eg:3 个 up.sql 和 3 个 down.sql。空数据库

    不加参数 N

    • 执行 up 命令,后面不加参数,升序执行所有的 up.sql 文件。顺序 1,2,3
    • 执行 down 命令,后面不加参数,降序执行当前 version 的 down.sql,直到1xxx_down.sql执行完。顺序 3,2,1

    加参数 N

    • 执行 up 2 命令,执行两个 up.sql 文件。顺序 1,2
    • 执行 down 1 命令,执行一个 down.sql文件。顺序 2
  • 每次 up 和 down 操作都可能会影响 schema_migrations 表。若 dirty 为 true。则代表操作失败,需手动修改

变更 up:

docker

1
migrate -database postgres://postgres:password@192.168.33.10:5432/example?sslmode=disable -path ./migrations up 1

本地测试

1
migrate -database postgres://postgres:password@localhost:5432/example?sslmode=disable -path ./migrations up 1

返回结果

1
1/u create_users_table (23.7245ms)

数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
example=# \d
关联列表
架构模式 | 名称 | 类型 | 拥有者
----------+-------------------+--------+----------
public | schema_migrations | 数据表 | postgres
public | users | 数据表 | postgres
public | users_user_id_seq | 序列数 | postgres
(3 行记录)


example=# \d users
数据表 "public.users"
栏位 | 类型 | 校对规则 | 可空的 | 预设
----------+------------------------+----------+----------+----------------------------------------
user_id | integer | | not null | nextval('users_user_id_seq'::regclass)
username | character varying(50) | | not null |
password | character varying(50) | | not null |
email | character varying(300) | | not null |
索引:
"users_pkey" PRIMARY KEY, btree (user_id)
"users_email_key" UNIQUE CONSTRAINT, btree (email)
"users_username_key" UNIQUE CONSTRAINT, btree (username)

回滚 down:

1
migrate -database postgres://postgres:password@localhost:5432/example?sslmode=disable -path ./migrations down 1

migrations down 后,数据库恢复到应用 create_users 之前的状态,users 表被删除,schema_migrations 表记录被删除

2.5 应用多次修改

1、第二次修改使用事务为 users 表添加 COLUMN

migrate create -ext sql -dir ./migrations -seq add_mood_to_users , migrations 目录下会增加 000002_add_mood_to_users.up.sql000002_add_mood_to_users.down.sql 两个文件。

000002_add_mood_to_users.up.sql

1
2
3
4
5
6
7
8
BEGIN;
CREATE TYPE enum_mood AS ENUM (
'happy',
'sad',
'neutral'
);
ALTER TABLE users ADD COLUMN IF NOT EXISTS mood enum_mood;
COMMIT;

000002_add_mood_to_users.down.sql

1
2
3
4
BEGIN;
ALTER TABLE users DROP COLUMN IF EXISTS mood;
DROP TYPE IF EXISTS enum_mood;
COMMIT;

2、第三次修改为 users 表增加 role_id 这个 COLUMN

migrate create -ext sql -dir ./migrations -seq add_roleid_to_users , migrations 目录下会增加 000003_add_roleid_to_users.up.sql000003_add_roleid_to_users.down.sql 两个文件。

000003_add_roleid_to_users.up.sql

1
ALTER TABLE users ADD COLUMN IF NOT EXISTS role_id INTEGER;

000003_add_roleid_to_users.down.sql

1
ALTER TABLE users DROP COLUMN IF EXISTS role_id;

3、

  • migrate up 执行 migrations 目录下所有的 up.sql 脚本。顺序:从 1->3 依次执行
1
migrate -database postgres://postgres:password@localhost:5432/example?sslmode=disable -path ./migrations up

返回结果

1
2
3
1/u create_users_table (24.4893ms)
2/u add_mood_to_users (35.9127ms)
3/u add_roleid_to_users (45.9152ms)
  • migrate down 执行 migrations 目录下所有的 up.sql 脚本。顺序:从 3->1 依次执行
1
2
3
migrate -database postgres://postgres:password@localhost:5432/example?sslmode=disable -path ./migrations down
Are you sure you want to apply all down migrations? [y/N]
y

返回结果

1
2
3
4
Applying all down migrations
3/d add_roleid_to_users (18.3408ms)
2/d add_mood_to_users (31.8805ms)
1/d create_users_table (47.9373ms)
  • migrate up 2。执行 1-2
1
migrate -database postgres://postgres:password@localhost:5432/example?sslmode=disable -path ./migrations up 2

返回结果

1
2
1/u create_users_table (17.9567ms)
2/u add_mood_to_users (28.0026ms)