Go-Zero整合Goose实现MySQL数据库版本管理


推荐阅读
【系列好文】go-zero从入门到精通(看了就会)
教程地址:https://blog.csdn.net/u011019141/article/details/139619172


Go-Zero整合Goose实现MySQL数据库版本管理的教程

在开发中,数据库迁移和版本管理是必不可少的工作。为了确保数据库架构与代码的同步,需要采用一定的技术手段,确保在每次代码升级时,自动增量修改变动的SQL脚本。

goose 是一个非常受欢迎的数据库迁移工具,可以帮助我们管理 MySQL 数据库的版本。

本文将详细介绍如何将 goosego-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. 核心步骤
  1. 打开数据库连接:通过 sqlx 或标准的 sql.Open 打开 MySQL 数据库连接。
  2. 设置 Goos 方言:告诉 goose 使用 MySQL 数据库。
  3. 执行迁移:使用 goose.Up() 方法执行迁移操作,goose.GetDBVersion 检查当前数据库的迁移版本。
  4. 错误处理和日志:对每个步骤都添加详细的错误处理和日志,确保在生产环境中能够快速定位问题。

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 可以帮助你轻松管理数据库架构的变更,确保数据库的版本一致性,并且在团队开发中减少冲突。

希望本教程能帮助你更好地理解和使用 goosego-zero,构建高效且可维护的数据库管理系统。

11. 拓展

如果是Java项目,请使用Flyway实现。
SpringBoot或者SpringCloud项目整合Flyway实现数据库版本管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955485.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日一题洛谷P1427 小鱼的数字游戏c++

#include<iostream> using namespace std; int main() {long long s[100] { 0 };int i 0;while (1) {cin >> s[i];if (s[i]0) {break;}i;}for (i; i > 0;i--) {if(s[i]!0)cout << s[i] << " ";}return 0; }

力扣 子集

回溯基础&#xff0c;一题多解&#xff0c;不同的回朔过程。 题目 求子集中&#xff0c;数组的每种元素有选与不选两种状态。因此在使用dfs与回溯时把每一个元素分别进行选与不选的情况考虑即可。可以先用dfs跳过当前元素即不选然后一直深层挖下去&#xff0c;直到挖到最深了即…

宇泰串口卡驱动在Ubuntu22.04编译、安装汇总

从官网下载驱动官网地址 上传到Ubuntu, 目录结构如下&#xff1a; 驱动源代码: 驱动代码是基于开源项目编译来的 编译路径不能有中文路径&#xff0c;否则可能有类似错误 源码是基于Linux2.3内核编译&#xff0c;我当前是6.8.0-51&#xff0c;数据结构有升级&#xff0c;需要调…

LSA更新、撤销

LSA的新旧判断&#xff1a; 1.seq&#xff0c;值越大越优先 2.chksum&#xff0c;值越大越优先 3.age&#xff0c;本地的LSA age和收到的LSA age作比较 如果差值<900s&#xff0c;认为age一致&#xff0c;保留本地的&#xff1a;我本地有一条LSA是100 你给的是400 差值小于…

运行fastGPT 第四步 配置ONE API 添加模型

上次已经装好了所有的依赖和程序。 下面在网页中配置One API &#xff0c;这个是大模型的接口。配置好了之后&#xff0c;就可以配置fastGPT了。 打开 OneAPI 页面 添加模型 这里要添加具体的付费模型的API接口填进来。 可以通过ip:3001访问OneAPI后台&#xff0c;**默认账号…

强化学习-蒙特卡洛方法

强化学习-数学理论 强化学习-基本概念强化学习-贝尔曼公式强化学习-贝尔曼最优公式强化学习-值迭代与策略迭代强化学习-蒙特卡洛方法 文章目录 强化学习-数学理论一、蒙特卡洛方法理论(Monte Carlo, MC)二、MC Basic2.1 算法拆解2.2 MC Basic算法 三、MC Exploring Starts3.1 …

【专题一 递归】21. 合并两个有序链表

1.题目解析 2.讲解算法原理 解法:递归-> 重复的子问题 重复子问题 ->函数头的设计 合并两个有序链表--->Node dfs(l1&#xff0c;l2) 只关心某一个子问题在做什么事情 ->函数体的设计 比大小l1→next dfs( l1.next, l2)return l1 递归的出口 if(l1null)return l2…

企业级NoSQL数据库Redis

1.浏览器缓存过期机制 1.1 最后修改时间 last-modified 浏览器缓存机制是优化网页加载速度和减少服务器负载的重要手段。以下是关于浏览器缓存过期机制、Last-Modified 和 ETag 的详细讲解: 一、Last-Modified 头部 定义:Last-Modified 表示服务器上资源的最后修改时间。 作…

FPGA车牌识别

基于FPGA的车牌识别主要包含以下几个步骤&#xff1a;图像采集、颜色空间转换、边缘检测、形态学处理&#xff08;腐蚀和膨胀&#xff09;、特征值提取、模板匹配、结果显示。先用matlab对原理进行仿真&#xff0c;后用vivado和modelsim进行设计和仿真。 一、1.图像采集采用ov…

客户案例:致远OA与携程商旅集成方案

一、前言 本项目原型客户公司创建于1992年,主要生产并销售包括糖果系列、巧克力系列、烘焙系列、卤制品系列4大类,200多款产品。公司具有行业领先的生产能力,拥有各类生产线100条,年产能超过10万吨。同时,经过30年的发展,公司积累了完善的销售网络,核心经销商已经超过1200个,超…

怎么修复损坏的U盘?而且不用格式化的方式!

当你插入U盘时&#xff0c;若电脑弹出“需要格式化才能使用”提示&#xff0c;且无法打开或读取其中的数据&#xff0c;说明U盘极有可能已经损坏。除此之外&#xff0c;若电脑在连接U盘后显示以下信息&#xff0c;也可能意味着U盘出现问题&#xff0c;需要修复损坏的U盘&#x…

贪心算法(题1)区间选点

输出 2 #include <iostream> #include<algorithm>using namespace std;const int N 100010 ;int n; struct Range {int l,r;bool operator <(const Range &W)const{return r<W.r;} }range[N];int main() {scanf("%d",&n);for(int i0;i&l…

2.使用Spring BootSpring AI快速构建AI应用程序

Spring AI 是基于 Spring Boot3.x 框架构建&#xff0c;Spring Boot官方提供了非常便捷的工具Spring Initializr帮助开发者快速的搭建Spring Boot应用程序,IDEA也集成了此工具。本文使用的开发工具IDEASpring Boot 3.4Spring AI 1.0.0-SNAPSHOTMaven。 1.创建Spring Boot项目 …

【Linux】Socket编程-TCP构建自己的C++服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; Socket 编程 TCP &#x1f98b; TCP socket API 详解&#x1f98b; 多线程远程命令执行&#x1f98b; 网络版计算器&#xff08;应用层自定义协议与序列化…

森林网络部署,工业4G路由器实现林区组网远程监控

在广袤无垠的林区&#xff0c;每一片树叶的摇曳、每一丝空气的流动&#xff0c;都关乎着生态的平衡与安宁。林区监控正以强大的力量&#xff0c;为这片绿色家园筑起一道坚固的防线。 工业 4G 路由器作为林区监控组网的守护者&#xff0c;凭借着卓越的通讯性能&#xff0c;突破…

数据库管理-第284期 奇怪的sys.user$授权(20250116)

数据库管理284期 20245-01-16 数据库管理-第284期 奇怪的sys.user$授权&#xff08;20250116&#xff09;1 问题2 CDB与PDB3 跨实例3.1 通过scanip访问数据库3.2 通过节点1的VIP访问数据库3.3 通过节点3的VIP访问数据库3.4 在节点3赋权后测试3.5 小结 总结 数据库管理-第284期 …

vue2配置跨域后请求的是本机

这个我来说明一下&#xff0c;因为我们公司的后端设置解决了跨域问题&#xff0c;所以我有很久没有看相关的内容了&#xff0c;然后昨天请求了需要跨域的接口&#xff0c;请求半天一直不对&#xff0c;浏览器显示的是本机地址&#xff0c;我以为是自己配置错了&#xff0c;后面…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中&#xff0c;51 单片机就像一颗独特的星辰&#xff0c;散发着神秘而迷人的光芒。对于无数电子爱好者而言&#xff0c;点亮 51 单片机上的第一颗 LED 灯&#xff0c;不仅仅是一次简单的操作&#xff0c;更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

Java技术栈 —— 如何把项目部署到公网?

如何把项目部署到公网&#xff1f; 一、准备工作1.1 获得一台云服务器1.2 安装SSH客户端 二、云服务器部署2.1 配置云服务器2.2 使用nginx部署1个或多个前端项目 三、访问测试四、访问控制 平常大部分人都是本地写写项目&#xff0c;然后通过localhost的方式去访问&#xff0c;…

春秋杯-WEB

SSTI 可以看到主页那里有个登录测试之后为ssti {{4*4}} fenjing梭哈即可得到payload {{((g.pop.__globals__.__builtins__.__import__(os)).popen(cat flag)).read()}}file_copy 看到题目名字为file_copy&#xff0c; 当输入路径时会返回目标文件的大小&#xff0c; 通…