Go-Zero整合Goose实现MySQL数据库版本管理
推荐阅读
【系列好文】go-zero从入门到精通(看了就会)
教程地址:https://blog.csdn.net/u011019141/article/details/139619172
Go-Zero整合Goose实现MySQL数据库版本管理的教程
在开发中,数据库迁移和版本管理是必不可少的工作。为了确保数据库架构与代码的同步,需要采用一定的技术手段,确保在每次代码升级时,自动增量修改变动的SQL脚本。
goose
是一个非常受欢迎的数据库迁移工具,可以帮助我们管理 MySQL 数据库的版本。
本文将详细介绍如何将 goose
与 go-zero
框架整合,实现 MySQL 数据库版本管理。
1. 介绍Goose和Go-Zero
-
Goose:Goose 是一个用于数据库迁移的工具,它支持多种数据库,并且可以通过SQL文件来定义数据库的变更。Goose的优势在于它简单易用,能够管理数据库的迁移、版本控制和回滚操作。
Goose Github仓库地址:https://github.com/pressly/goose
参考实现:https://pressly.github.io/goose/blog/2021/embed-sql-migrations/#but-why
-
Go-Zero:Go-Zero 是一个高效的 Go 微服务框架,提供了许多用于构建微服务的工具,比如代码生成、RPC框架、消息队列等。Go-Zero 也集成了数据库访问层,通过
sqlx
包操作 MySQL、PostgreSQL 等数据库。
本文将结合这两个工具,通过Go-Zero的数据库管理,使用Goose进行MySQL数据库的版本控制与迁移。
2. 项目结构
假设你已经有一个Go-Zero项目,下面是项目的结构:
your-project/
|-- migrations/ # 数据库迁移文件存放目录
|-- main.go # 程序入口
|-- go.mod # Go模块管理文件
|-- go.sum # Go模块依赖文件
3. 安装Goose
首先,你需要安装 goose
工具:
go get -u github.com/pressly/goose
安装成功后,可以通过命令行使用 goose
来管理数据库迁移。
4. 创建数据库迁移文件
数据库迁移文件用于定义 MySQL 数据库表和字段的更新操作。
在 migrations
目录下生成一个类似 00001_add_table.sql
的文件。
5. 编写迁移SQL
打开生成的 SQL 文件,定义数据库的表和字段。例如:
-- +goose Up
CREATE TABLE demo1 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO demo1 (name, age) VALUES ('Alice', 30);
CREATE TABLE demo2 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE demo3 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE demo4 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- +goose Up
:表示执行数据库迁移时的 SQL 语句。-- +goose Down
:表示回滚迁移时执行的 SQL 语句。
确保 SQL 文件没有多余的空格、换行或不可见字符,特别是文件编码格式应为 UTF-8。
来自Github仓库的说明:
每个迁移文件必须只有一个-- +goose Up注释。-- +goose Down注释是可选的。如果文件同时具有两个注释,则–
+goose Up注释必须先出现。注意注释中的注解。后面的任何语句都-- +goose Up将作为前向迁移的一部分执行,后面的任何语句都-- +goose
Down将作为回滚的一部分执行。默认情况下,所有迁移都在事务中运行。但是,某些语句(CREATE DATABASE如)无法在事务中运行。您可以选择将其添加-- +goose
NO TRANSACTION到迁移文件的顶部,以跳过该特定迁移文件中的事务。此文件中的 Up 和 Down 迁移都将在无事务的情况下运行。默认情况下,SQL 语句以分号分隔 - 事实上,查询语句必须以分号结尾才能被 goose 正确识别。
6. 在Go-Zero中使用Goose
为了在 Go-Zero 中执行数据库迁移,我们需要将 goose
集成到 Go-Zero 的数据库管理流程中。
1. 配置数据库连接
在 Go-Zero 中,我们通过 sqlx
来操作 MySQL 数据库,因此首先需要配置好数据库连接。
package main
import (
"database/sql"
"log"
"github.com/pressly/goose"
_ "github.com/go-sql-driver/mysql" // MySQL 驱动
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
func migrateDatabase() {
// 配置 MySQL 连接
dsn := "root:123456@tcp(192.168.2.204:3306)/test?charset=utf8mb4"
log.SetFlags(log.LstdFlags | log.Lshortfile) // 更详细的日志格式,包括时间戳和文件行号
// 打开 MySQL 数据库连接
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatalf("数据库迁移同步操作:数据库连接失败: %v", err) // 记录错误并退出
return
}
defer db.Close() // 确保数据库连接在函数退出时关闭
log.Println("数据库迁移同步操作:开始执行数据库迁移。")
// 设置 Goose 数据库迁移工具的方言
goose.SetDialect("mysql")
// 执行数据库迁移
if err := goose.Up(db, "migrations"); err != nil {
log.Fatalf("数据库迁移同步操作:数据库迁移失败: %v", err) // 记录迁移失败的错误
return
} else {
log.Println("数据库迁移同步操作:数据库已成功迁移到最新版本。")
}
version, err := goose.GetDBVersion(db)
log.Println("数据库迁移同步操作:当前数据库版本为:", version)
log.Println("数据库迁移同步操作:数据库迁移和查询操作完成。")
}
func main() {
// 调用数据库迁移函数
migrateDatabase()
}
2. 核心步骤
- 打开数据库连接:通过
sqlx
或标准的sql.Open
打开 MySQL 数据库连接。 - 设置 Goos 方言:告诉
goose
使用 MySQL 数据库。 - 执行迁移:使用
goose.Up()
方法执行迁移操作,goose.GetDBVersion
检查当前数据库的迁移版本。 - 错误处理和日志:对每个步骤都添加详细的错误处理和日志,确保在生产环境中能够快速定位问题。
7. 运行迁移
在 main()
函数中调用 migrateDatabase()
,程序会自动执行数据库的迁移操作。
go run main.go
这将会执行位于 migrations
目录下的 SQL 文件,并根据版本顺序自动更新数据库表。如果迁移执行成功,日志会输出成功信息;如果失败,则会输出详细的错误信息。
运行结果:
2025/01/15 14:27:18 app.go:81: 数据库迁移同步操作:开始执行数据库迁移。
2025/01/15 14:27:18 log.go:29: OK 00001_add_table.sql
2025/01/15 14:27:19 log.go:29: OK 00002_alter_table.sql
2025/01/15 14:27:19 log.go:29: OK 00003_delete_table.sql
2025/01/15 14:27:19 log.go:30: goose: no migrations to run. current version: 3
2025/01/15 14:27:19 app.go:91: 数据库迁移同步操作:数据库已成功迁移到最新版本。
2025/01/15 14:27:19 app.go:95: 数据库迁移同步操作:当前数据库版本为: 3
2025/01/15 14:27:19 app.go:96: 数据库迁移同步操作:数据库迁移和查询操作完成。
8. 最佳实践
-
版本控制:在团队开发中,确保所有的迁移文件都通过版本控制工具(如Git)进行管理。这样可以避免迁移文件丢失或冲突。
-
迁移顺序:保持迁移文件的顺序,
goose
会根据文件名中的时间戳自动排序。 -
回滚迁移:在开发过程中,使用
goose down
来回滚不需要的迁移版本,确保数据库表结构可以回到之前的版本。 -
数据库备份:在执行数据库迁移之前,特别是在生产环境中,务必备份数据库,以防止因迁移失败导致的数据丢失。
9. 附加
在 migrations
目录下创建以下SQL文件,进行不同版本SQL脚本的测试。
00002_alter_table.sql
-- +goose Up
CREATE TABLE demo5 (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE demo1
ADD COLUMN `test` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '测试字段' AFTER `created_at`;
UPDATE demo1 SET age = 31 WHERE name = 'Alice';
00003_delete_table.sql
-- +goose Up
DROP TABLE IF EXISTS demo1;
DROP TABLE IF EXISTS demo2;
DROP TABLE IF EXISTS demo3;
DROP TABLE IF EXISTS demo4;
DROP TABLE IF EXISTS demo5;
goose_db_version
成功运行程序后,会自动在数据库生成数据库表goose_db_version
,用来记录每个版本执行情况,如果修改某个版本SQL,需删除对应执行记录,重新运行程序!!!
10. 总结
本文介绍了如何将 goose
集成到 go-zero
框架中,通过数据库迁移管理 MySQL 数据库的版本控制。在实际项目中,使用 goose
可以帮助你轻松管理数据库架构的变更,确保数据库的版本一致性,并且在团队开发中减少冲突。
希望本教程能帮助你更好地理解和使用 goose
和 go-zero
,构建高效且可维护的数据库管理系统。
11. 拓展
如果是Java项目,请使用Flyway实现。
SpringBoot或者SpringCloud项目整合Flyway实现数据库版本管理