在我们使用数据库的时候,迁移模式是我们在整个应用程序生命周期中经常必须完成的一项重要任务,以适应新的业务需求,在本章中,将学习如何使用Golang编写和运行数据库迁移(DB Migration)。
所以,这里需要使用一个Golang库,github.com/golang-migr…,这个库适用于许多不同的数据库引擎,包括:PostgreSQL、SQLite、MySQL/ MariaDB、MongoDB等等,具体可以参考官方文档。
1、安装migrate库
打开文档,github.com/golang-migr…,这里,因为我使用的Mac,所以,用brew的安装方式:
brew install golang-migrate
其他操作系统的安装方式,请查看该库的文档。
安装好后,通过 migrate --help,可以查看到该工具的使用帮助。
几个常用的命令:
create我们可以使用它来创建新的迁移goto将迁移到指定的版本up或者down向上或向下迁移
2、创建Golang项目
新建个目录simplebank
mkdir simpleblank
进入这个目录,并创建db/migration目录,用于保存我们所有的迁移文件。
cd simpleblank
mkdir -p db/migration
接着,我们创建第一个迁移文件,来初始化银行项目的数据库表。
执行命令:
migrate create -ext sql -dir db/migration -seq init_schema
-ext sql 指定我们要创建的是sql脚本
-dir db/migration 指定我们存放脚本的目录
-seq 按顺序设置迁移文件的版本号
init_schema 迁移文件的名字
执行结果如下:
它为我们生成了
2个脚本,文件名前缀都有版本1,一个up脚本,一个down脚本,为什么这样生成,因为,基本上这是编写数据库迁移时的最佳实践。
up/down迁移流程图:
up老版本的数据库迁移到新数据库的流程图,如下:
down新版本迁移到老版本的流程图:
上图中,应该为
x.down.sql
3、编辑Golang项目
我这里使用vscode编辑器,使用它打开我们刚才创建的目录simpleblank,然后,把之前生成好的sql脚本文件打开,复制里面的内容到db/migration/000001_init_schema.up.sql文件中;
对于db/migration/000001_init_schema.down.sql文件内,我们应该恢复up脚本所做的更改,up脚本里会创建3个表,这里down文件里需要把它们都删除掉,内容如下:
DROP TABLE IF EXISTS entries;
DROP TABLE IF EXISTS transfers;
DROP TABLE IF EXISTS accounts;
4、Docker容器里创建银行数据库
之后,我们执行它,在这之前,我们先检查一下上一节配置的postgres容器是否任然还在运行。
docker ps
这里,再介绍一下,如何停止运行它,
docker stop
docker stop postgres14
之后,再运行 docker ps,在列表里将不会看到它了。
通过,docker ps -a,可以查看到所有的容器,包括不在运行的。
要再启动它,只需执行如下命令:
docker start postgres14
start后面的参数,可以为容器名称或容器的ID
使用docker exec命令来访问postgres容器的shell,由于我们使用的是postgres alpine镜像,因此,它没有ubuntu中的/bin/bash,所以,我们使用/bin/sh shell 替代,如下:
docker exec -it postgress14 /bin/sh
在shell内部,我们可以访问所有标准的linux命令。
在
shell里面,我们使用createdb命令为我们的银行项目创建一个新的数据库,使用--username=root选项表示以root用户身份连接,--owner=root表示创建的数据库也将属于root用户,最后一个参数simple_bank是数据库的名称。
createdb --username=root --owner=root simple_bank
这样,数据库就创建完成了。
使用psql命令访问它的控制台
psql simple_bank
命令\q退出控制台,同样,也可以使用命令删除数据库
dropdb simple_bank
使用命令exit退出容器
在容器外面,我们也可以直接使用
docker exec命令运行createdb
docker exec -it postgres14 createdb --username=root --owner=root simple_bank
在容器外,直接进入psql控制台
docker exec -it postgres14 psql -U root simple_bank
5、创建项目的Makefile文件
在我们的项目根目录下,创建一个空的Makefile文件
然后,在文件里面新增一个
createdb命令来创建银行数据库,dropdb命令来删除数据库,这些命令可以在团队开发时,让团队成员轻松的在他们本地机器上配置项目环境以便于开发。
Makefile文件的内容:
createdb:
docker exec -it postgres14 createdb --username=root --owner=root simple_bank
dropdb:
docker exec -it postgres14 dropdb simple_bank
.PHONY: createdb, dropdb
这样,在终端里执行命令make dropdb,就可以调用删除数据库操作了。
接下来,让我们把启动
postgres数据库容器的命令也加到Makefile文件里来,添加之后Makefile文件的内容如下:
postgres:
docker run --name postgres14 -e POSTGRES_PASSWORD=123456 -e POSTGRES_USER=root -p 5432:5432 -d postgres:14-alpine
createdb:
docker exec -it postgres14 createdb --username=root --owner=root simple_bank
dropdb:
docker exec -it postgres14 dropdb simple_bank
.PHONY: postgres, createdb, dropdb
现在,我们先在终端中停止postgres容器,
docker stop postgres14
然后,将容器删除
docker rm postgres14
使用命令 make postgres,来启动一个新的postgres容器
使用命令
make createdb,创建数据库,是不是很简单了。
使用navicat,连接数据库,来查看一下,有了一个空的simple_bank数据库
6、执行第一次迁移
进入项目目录的终端,执行命令migrate,--path db/migration指定迁移文件的路径,--database="postgresql://root:123456@localhost:5432/simple_bank",指定连接数据库的参数,-verbose让migrate打印详细的日志,最后,使用参数up告诉migrate运行migrate up
migrate --path db/migration --database="postgresql://root:123456@localhost:5432/simple_bank" -verbose up
这里,出了个错误,服务器没有启用SSL
error: pq: SSL is not enabled on the server
这是因为,我们的postgres容器默认不启用SSL,所以,我们需要在数据库连接字符串上增加 sslmode=disable 参数,如下:
migrate --path db/migration --database="postgresql://root:123456@localhost:5432/simple_bank?sslmode=disable" -verbose up
再次运行,我们看到迁移执行成功了。
我们,在
navicat中刷新一下simple_bank数据库,可以看到出现了4个表:
其中,
schema_migrations表中,保存最新的迁移版本。在这里,里面的version是1,因为我们只运行了1个迁移文件。dirty告诉我们最后一次迁移是否失败。
如果失败,我们必须查看并修复问题所在,直到成功。
现在,我们把migrate up和migrate down命令也添加到Makefile文件中,如下:
postgres:
docker run --name postgres14 -e POSTGRES_PASSWORD=123456 -e POSTGRES_USER=root -p 5432:5432 -d postgres:14-alpine
createdb:
docker exec -it postgres14 createdb --username=root --owner=root simple_bank
dropdb:
docker exec -it postgres14 dropdb simple_bank
migrateup:
migrate --path db/migration --database="postgresql://root:123456@localhost:5432/simple_bank?sslmode=disable" -verbose up
migratedown:
migrate --path db/migration --database="postgresql://root:123456@localhost:5432/simple_bank?sslmode=disable" -verbose down
.PHONY: postgres, createdb, dropdb, migrateup, migratedown
运行一下看看,make migratedown,会出现一个问题,是否确认降级,这里,我们输入y
再次,刷新
navicat,可以看到,数据库表删除掉了,并且schema_migrations表中的记录也清掉了。
再执行make migrateup,数据表又重新生成好了。
这样,本节数据库迁移就完成了。下一节,将学习如何从SQL中自动生成Golang的CRUD代码,并比较GORM、dbsql、sqlx、sqlc