golang MySQL纯SQL模式分片与在线表结构变更管理插件库skeema的使用

Golang MySQL纯SQL模式分片与在线表结构变更管理插件库Skeema的使用

Skeema简介

Skeema

Skeema是一个使用纯SQL以声明式方式管理MySQL和MariaDB模式变更的工具。Skeema CLI工具允许您:

  • CREATE TABLE语句导出到文件系统,以便在Git仓库中跟踪
  • 将模式仓库中的变更与实时数据库进行差异比较,自动生成DDL
  • 管理多个环境(如开发、预发布、生产)并轻松保持同步
  • 配置使用在线模式变更工具(如pt-online-schema-changegh-ostspirit)来执行ALTER TABLE
  • 应用可配置的linter规则,主动发现模式设计问题并执行公司策略

安装Skeema

# 在Linux上安装
curl -sSL https://www.skeema.io/download/linux | tar -xz -C /usr/local/bin skeema

# 在MacOS上安装
brew install skeema/tap/skeema

Golang中使用Skeema的示例

以下是一个完整的Golang示例,展示如何使用Skeema管理MySQL分片和在线表结构变更:

package main

import (
	"fmt"
	"os/exec"
	"log"
)

func main() {
	// 初始化Skeema工作目录
	err := initSkeemaWorkspace()
	if err != nil {
		log.Fatalf("初始化Skeema工作目录失败: %v", err)
	}

	// 从数据库拉取当前模式
	err = pullSchemaFromDB()
	if err != nil {
		log.Fatalf("从数据库拉取模式失败: %v", err)
	}

	// 修改本地模式文件
	err = modifySchemaFile()
	if err != nil {
		log.Fatalf("修改模式文件失败: %v", err)
	}

	// 预览变更
	err = previewChanges()
	if err != nil {
		log.Fatalf("预览变更失败: %v", err)
	}

	// 应用变更到数据库
	err = applyChanges()
	if err != nil {
		log.Fatalf("应用变更失败: %v", err)
	}

	fmt.Println("模式变更成功完成!")
}

func initSkeemaWorkspace() error {
	// 创建Skeema工作目录并初始化配置
	cmd := exec.Command("skeema", "init", "--dir", "./schema", 
		"--host", "mysql-shard1.example.com", 
		"--schema", "myapp",
		"--user", "admin",
		"--password", "secret")
	
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%v: %s", err, output)
	}
	return nil
}

func pullSchemaFromDB() error {
	// 从数据库拉取当前模式到本地文件
	cmd := exec.Command("skeema", "pull", "--dir", "./schema")
	
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%v: %s", err, output)
	}
	return nil
}

func modifySchemaFile() error {
	// 在实际应用中,这里会通过程序修改模式文件
	// 示例中我们只是模拟这个操作
	fmt.Println("模拟修改本地模式文件...")
	return nil
}

func previewChanges() error {
	// 预览将要对数据库做的变更
	cmd := exec.Command("skeema", "diff", "--dir", "./schema", "--safe-below-size=1")
	
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%v: %s", err, output)
	}
	
	fmt.Printf("预览变更:\n%s\n", output)
	return nil
}

func applyChanges() error {
	// 实际应用变更到数据库
	// 使用gh-ost进行在线变更
	cmd := exec.Command("skeema", "push", "--dir", "./schema", 
		"--alter-wrapper", "gh-ost",
		"--alter-wrapper-opt", "allow-master-master=true",
		"--alter-wrapper-opt", "cut-over=default",
		"--alter-wrapper-opt", "exact-rowcount=true")
	
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%v: %s", err, output)
	}
	
	fmt.Printf("变更已应用:\n%s\n", output)
	return nil
}

分片管理示例

以下是一个使用Skeema管理MySQL分片的示例:

package main

import (
	"fmt"
	"os/exec"
	"log"
)

func main() {
	shards := []string{
		"mysql-shard1.example.com",
		"mysql-shard2.example.com",
		"mysql-shard3.example.com",
	}

	for _, shard := range shards {
		err := manageShard(shard)
		if err != nil {
			log.Printf("分片 %s 管理失败: %v", shard, err)
		}
	}
}

func manageShard(host string) error {
	// 为每个分片创建单独的环境目录
	dir := fmt.Sprintf("./schema/%s", host)
	
	// 初始化分片配置
	cmd := exec.Command("skeema", "init", "--dir", dir,
		"--host", host,
		"--schema", "myapp",
		"--user", "admin",
		"--password", "secret")
	
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("初始化分片配置失败: %v: %s", err, output)
	}

	// 拉取分片当前模式
	cmd = exec.Command("skeema", "pull", "--dir", dir)
	output, err = cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("拉取分片模式失败: %v: %s", err, output)
	}

	// 应用变更到分片
	cmd = exec.Command("skeema", "push", "--dir", dir,
		"--alter-wrapper", "gh-ost")
	
	output, err = cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("应用变更到分片失败: %v: %s", err, output)
	}

	fmt.Printf("分片 %s 管理完成:\n%s\n", host, output)
	return nil
}

使用Skeema进行在线表结构变更

Skeema支持多种在线模式变更工具,以下是配置示例:

# .skeema 配置文件示例
[production]
host=mysql-prod.example.com
user=admin
password=secret
schema=myapp

# 使用pt-online-schema-change进行在线变更
alter-wrapper=pt-online-schema-change
alter-wrapper-opt="--max-load", "Threads_running=50"
alter-wrapper-opt="--critical-load", "Threads_running=100"
alter-wrapper-opt="--chunk-size=1000"
alter-wrapper-opt="--max-lag=5"

# 或者使用gh-ost
# alter-wrapper=gh-ost
# alter-wrapper-opt="--allow-master-master"
# alter-wrapper-opt="--cut-over=default"
# alter-wrapper-opt="--exact-rowcount"

[lint]
# 配置linter规则
rules=engine,charset,auto-inc,zero-date

最佳实践

  1. 版本控制:将Skeema生成的文件纳入Git版本控制
  2. 代码审查:对模式变更使用Pull Request流程
  3. 环境隔离:为不同环境(开发、测试、生产)使用不同的配置
  4. 自动化:将Skeema集成到CI/CD流程中
  5. 备份:在执行重大变更前备份数据库

总结

Skeema是一个强大的工具,可以帮助Golang开发者以声明式的方式管理MySQL模式变更,特别是在分片环境中。通过将模式定义存储在代码仓库中,并使用Skeema CLI工具进行变更管理,可以实现更安全、更可预测的数据库模式演进。


更多关于golang MySQL纯SQL模式分片与在线表结构变更管理插件库skeema的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang MySQL纯SQL模式分片与在线表结构变更管理插件库skeema的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Skeema: Golang MySQL分片与在线表结构变更管理工具

Skeema 是一个用于管理MySQL数据库架构的纯SQL模式工具,特别适合在分片环境和需要在线表结构变更的场景中使用。下面我将详细介绍Skeema的功能特点以及在Golang中的使用方式。

Skeema 核心功能

  1. 纯SQL模式管理 - 使用SQL文件表示数据库结构
  2. 分片支持 - 轻松管理多个分片的表结构
  3. 在线Schema变更 - 支持gh-ost或pt-online-schema-change
  4. 版本控制集成 - 与Git等版本控制系统完美配合
  5. 环境差异管理 - 管理开发、测试和生产环境间的差异

Golang中使用Skeema

虽然Skeema本身是用Perl编写的,但我们可以通过命令行或系统调用的方式在Golang项目中集成它。

安装Skeema

首先需要在系统中安装Skeema:

# 对于基于Debian的系统
curl -s https://packagecloud.io/install/repositories/skeema/io/script.deb.sh | sudo bash
sudo apt-get install skeema

Golang集成示例

package main

import (
	"fmt"
	"os/exec"
	"log"
)

// 执行Skeema命令的辅助函数
func runSkeemaCommand(args ...string) (string, error) {
	cmd := exec.Command("skeema", args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("skeema command failed: %v\nOutput: %s", err, output)
	}
	return string(output), nil
}

func main() {
	// 示例1: 初始化Skeema工作目录
	output, err := runSkeemaCommand("init", 
		"--host", "mysql-cluster.example.com",
		"--schema", "mydatabase",
		"--dir", "./schema")
	if err != nil {
		log.Fatalf("初始化失败: %v", err)
	}
	fmt.Println("初始化成功:", output)

	// 示例2: 推送变更到生产环境
	output, err = runSkeemaCommand("push", 
		"--host", "mysql-prod.example.com",
		"--allow-unsafe",
		"--dir", "./schema")
	if err != nil {
		log.Fatalf("推送变更失败: %v", err)
	}
	fmt.Println("变更推送成功:", output)

	// 示例3: 使用gh-ost执行在线DDL变更
	output, err = runSkeemaCommand("ddl", 
		"--alter-wrapper", "gh-ost",
		"--alter-wrapper-options", "'--allow-on-master --initially-drop-ghost-table'",
		"--dir", "./schema")
	if err != nil {
		log.Fatalf("DDL变更失败: %v", err)
	}
	fmt.Println("DDL变更执行成功:", output)
}

Skeema配置文件示例

Skeema使用.skeema配置文件来管理不同环境的连接信息:

# .skeema 配置文件示例

[production]
host="mysql-prod.example.com"
port=3306
user="admin"
password="securepassword"
schema="mydatabase"
environment="production"

[staging]
host="mysql-staging.example.com"
port=3306
user="admin"
password="stagingpassword"
schema="mydatabase"
environment="staging"

[dev]
host="localhost"
port=3306
user="root"
password=""
schema="mydatabase"
environment="development"

[options]
# 使用gh-ost进行在线schema变更
alter-wrapper="gh-ost"
alter-wrapper-options="--allow-on-master --initially-drop-ghost-table"

分片环境管理

对于分片环境,Skeema可以通过目录结构来管理:

schema/
├── shard1/
│   ├── .skeema
│   └── *.sql
├── shard2/
│   ├── .skeema
│   └── *.sql
└── shard3/
    ├── .skeema
    └── *.sql

每个分片目录包含自己的连接配置和SQL文件,可以统一或分别管理。

最佳实践

  1. 版本控制 - 将SQL文件纳入Git版本控制
  2. CI/CD集成 - 在部署流程中加入Skeema校验
  3. 环境隔离 - 为每个环境维护单独的配置
  4. 变更审查 - 在推送前使用skeema diff审查变更
  5. 备份策略 - 在执行重大变更前确保有备份

替代方案

如果需要在纯Golang环境中实现类似功能,可以考虑以下库:

  • github.com/go-sql-driver/mysql + 自定义迁移逻辑
  • github.com/golang-migrate/migrate 用于数据库迁移
  • github.com/skeema/tengo (Skeema的Go端口)

Skeema提供了一种声明式、基于SQL的数据库架构管理方法,特别适合需要处理分片和在线变更的MySQL环境。虽然它不是纯Go实现,但可以轻松集成到Go工作流程中。

回到顶部