Golang里数据库migration方案

Python中如果用SQLAlchemy的话,一般会用alembic来做migration。那么,Go呢?我一般用这个:

https://github.com/golang-migrate/migrate

官方的用法是生成migration文件(其实就是sql)时用命令行,升级时也可以用命令行。不过我更喜欢把升级文件和代码一起打包到二进制文件里。

我们依次来看。

创建migration文件

这个很简单,首先你要在自己电脑上装上 migrate 这个二进制:

curl -L https://github.com/golang-migrate/migrate/releases/download/$version/migrate.$platform-amd64.tar.gz | tar xvz

我是放到了 /usr/local/bin 下,其实也可以放到 $PATH 的任一自定义目录里。

生成migration文件,则执行以下命令即可:

$ migrate create -ext sql -dir ./migrations -seq create_user_table

执行之后,就会在 ./migrations 文件夹下,创建两个文件,都会包含 -seq 后的那一段,以 up.sqldown.sql 结尾。分别对应升级和降级操作该要执行的SQL。

migration操作,就写在对应的文件里。

升级

除了继续用 migrate 这个命令来进行升级降级操作,我们还可以把操作结合到程序里,我更喜欢这样做,好处如下:

  • 不用每个地方都打包 migrate 这个命令,或者安装这个二进制文件
  • 不用把migrations文件夹到处同步

咋做呢?这个时候就该祭出 go-bindata 这个包了,它的原理就是读文件,把文件的内容生成到一个 bindata.go 文件里,然后就可以通过内置的api,读取其中的内容。

那怎么结合到我们的应用里呢?直接上代码:

package main

import (
    "flag"
)

var migrateUp = flag.Bool("migrateUp", false, "run migration")

func main() {
    // ...
	if *migrateUp {
		s := bindata.Resource(migrations.AssetNames(),
			func(name string) ([]byte, error) {
				return migrations.Asset(name)
			})

		d, err := bindata.WithInstance(s)
		if err != nil {
			logrus.Panicf("failed to get migrations: %s", err)
		}
		m, err := migrate.NewWithSourceInstance("go-bindata", d, config.MigrateDBURL)
		if err != nil {
			logrus.Panicf("failed to get migrations: %s", err)
		}
		err = m.Up()
		if err != nil {
			logrus.Panicf("failed to migrate: %s", err)
		}
		return
	}
    // ...
}

就是介样,我们就可以愉快的把migration也编译到应用里,然后继续愉快的一个二进制包到处丢了。

当然了,要想使用 go-bindata,也得安装:

$ go get -u github.com/go-bindata/go-bindata/...

然后我在Makefile里加上这么一个动作:

bindata:
	cd migrations && go-bindata -pkg migrations .

duang,大功告成。


微信公众号
关注公众号,获得及时更新

更多文章
  • Linux下当笔记本合上盖子之后只使用扩展显示器
  • Ubuntu 18.04 dhcp更换新IP
  • Python中的新式类(new style class)和老式类(old style class)
  • Python Requests 简明教程
  • 密码技术简明教程(三):证书和TLS
  • 密码技术简明教程(二):散列、消息认证码和数字签名
  • SEO学习笔记
  • 密码技术简明教程(一):对称加密和非对称加密
  • Kubernetes 笔记
  • go mod 和 logrus 路径大小写的问题
  • Flask自动加载Blueprint
  • 在KVM里安装Minikube
  • 搞定面试中的系统设计题
  • Crontab + Sendmail实现定时任务并且通知
  • Nginx设置Referer来防止盗图