Gaea is a mysql proxy, it's developed by xiaomi b2c-dev team.

LICENSE Build Status Go Report Card

简介

Gaea是小米中国区电商研发部研发的基于mysql协议的数据库中间件,目前在小米商城大陆和海外得到广泛使用,包括订单、社区、活动等多个业务。Gaea支持分库分表、sql路由、读写分离等基本特性,更多详细功能可以参照下面的功能列表。其中分库分表方案兼容了mycat和kingshard两个项目的路由方式。Gaea在设计、实现阶段参照了mycat、kingshard和vitess,并使用tidb parser作为内置的sql parser,在此表达诚挚感谢。为了方便使用和学习Gaea,我们也提供了详细的使用和设计文档,也欢迎大家多多参与。

功能列表

基础功能

  • 多集群
  • 多租户
  • SQL透明转发
  • 慢SQL指纹
  • 错误SQL指纹
  • 注解路由
  • 慢日志
  • 读写分离,从库负载均衡
  • 自定义SQL拦截与过滤
  • 连接池
  • 配置热加载
  • IP/IP段白名单
  • 全局序列号

分库、分表功能

  • 分库: 支持mycat分库方式
  • 分表: 支持kingshard分表方式
  • 聚合函数: 支持max、min、sum、count、group by、order by等
  • join: 支持分片表和全局表的join、支持多个分片表但是路由规则相同的join

架构图

gaea架构图

集群部署图

gaea集群部署图

如上图所示, 部署一套gaea-cc和etcd可用来管理多套gaea集群, 负责集群内namespace配置的增删改查. gaea-cc的HTTP接口文档

安装使用

设计与实现

Roadmap

  • 支持配置加密存储,开关
  • 支持执行计划缓存
  • 支持事务追踪
  • 支持二级索引
  • 支持分布式事务
  • 支持平滑的扩容、缩容
  • 后端连接池优化 (按照请求时间排队)

自有开发模块

  • backend
  • cmd
  • log
  • models
  • proxy/plan
  • proxy/router(kingshard路由方式源自kingshard项目本身)
  • proxy/sequence
  • server

外部模块

  • mysql(google vitess、tidb、kingshard都有引入)
  • parser(tidb)
  • stats(google vitess,打点统计)
  • util(混合)

社区

gitter

Gitter

钉钉

钉钉

Comments
  • test: 补齐 dc 直连的单元测试

    test: 补齐 dc 直连的单元测试

    补齐 dc 直连的单元测试,包含 一开始的 initial handshake packet from MariaDB 和之后 Gaea 的回应

    主要变更的文档有三份,如下

    Gaea/backend/direct_connection_test.go Gaea/backend/direct_connection_cn.md Gaea/backend/direct_connection_en.md

    之前 pipeTest 包也进行修改,包含新增函数和部份函数改名

  • test: add container test

    test: add container test

    新增容器测试 1 由 Gaea 去触发容器直接启动进行测试,测试完成后,删除容器 2 不使用 docker ,而是使用 containerd 3 目前支援容器支援的上锁,但不支援群组容器,也就是一次启动多个容器进行测试,下一阶再去制作 4 目前也支援容器 log 日志,日志位置在 Gaea/util/mocks/containerTest/logs,会记录所有容器的执行状况 5 containerd 不像 docker 可以很简单的设定非 root 身份去执行,要由非 root 身份去执行的话,要花时间设定,但是如果要省下此步骤的话,就直接用 root 身份去执行就好 6 containerd 相对于 docker ,为少了一层去执行容器,未来将会成为主流 7 所有操作的细节在 Gaea/util/mocks/containerTest/README.md,尤其在后半段,有说明操作细节 8 容器没有固定的 IP 位置,用子网切割就可以克服这个问题 9 目前提供一个实际的测试例子,在 Gaea/backend/direct_connection_test.go 的 TestContainersInterference 函数里 10 这功能要好用,还要在加快容器的执行速度,并增加功能

  • make时报错

    make时报错

    go: finding gopkg.in/resty.v1 v1.12.0 go: google.golang.org/[email protected]: unrecognized import path "google.golang.org/genproto" (https fetch: Get https://google.golang.org/genproto?go-get=1: dial tcp 216.239.37.1:443: i/o timeout) go: error loading module requirements Makefile:12: recipe for target 'gaea' failed make: *** [gaea] Error 1

  • feature: 把 Etcd V3 API 整合到 Gaea

    feature: 把 Etcd V3 API 整合到 Gaea

    目前把 Etcd V3 API 整合到 Gaea

    1 保留原有的 Etcd V2 Api,在设定文档 Gaea/etc/gaea.ini 的设定值不变,为 config_type=etcd,这样大家就不用去修改设定值 2 现在设定文档 Gaea/etc/gaea.ini,支援Etcd V3 API 的设定值为 config type=etcdv3

    接下来会处理 gaea cc 也会内置一个可视化的配置管理功能

  • gaea-cc在配置两阶段提交时,没考虑proxy返回的错误信息,可能会导致proxy进程崩溃。

    gaea-cc在配置两阶段提交时,没考虑proxy返回的错误信息,可能会导致proxy进程崩溃。

    gaea-cc在配置两阶段提交时,请求 /api/proxy/config/prepare/:namespace 接口后,没有判断接口返回的内容,只判断了请求是否成功,接着直接去请求了/api/proxy/config/commit/:namespace接口,在以下情况会导致proxy进程崩溃。

    如提交一个不存在的分片类型,prepare接口会报 “err: unknown rule type”,但是cc忽略了这个错误直接去请求 commit接口后,proxy通过ReloadNamespaceCommit方法把 Manager.switchIndex置为1,此时 Manager.namespaces下标1为nil(因为prepare接口并没有解析成功刚刚提交的错误分片类型namespace配置),导致Manager.startConnectPoolMetricsTask()方法中的这行代码for nameSpaceName, _ := range m.namespaces[current].namespaces引发错误"invalid memory address or nil pointer dereference"。

  • 请问如何将namespace的json配置数据导入到etcd呢?

    请问如何将namespace的json配置数据导入到etcd呢?

    对etcd不是很熟悉,用这样的命令将etc/namespaces下的json串导入到etcd后

    ./etcdctl put /gaea/file/namespace/test_namespace_1.json "{"name":"test_namespace_1","online":true,"read_only":false,"allowed_dbs":{"test_db":true},"slow_sql_time":"1000","black_sql":[""],"allowed_ip":null,"slices":[{"name":"slice-0","user_name":"root","password":null,"master":"127.0.0.1:3306","slaves":null,"statistic_slaves":null,"capacity":12,"max_capacity":24,"idle_timeout":60}],"shard_rules":[{"db":"test_db","table":"log","type":"date_month","key":"created_at","slices":["slice-0"],"date_range":["201804-201910"]}],"users":[{"user_name":"root","password":"root","namespace":"test_namespace_1","rw_flag":2,"rw_split":1,"other_property":0}],"default_slice":"slice-0","global_sequences":null}"
    

    启动Gaea服务

    bogon:Gaea user$ ./bin/gaea -config etc/gaea.ini
    Build Version Information:Version: 666d59e9f7ea563733299d97260ee43307881d70
    GitRevision: 666d59e9f7ea563733299d97260ee43307881d70
    User: [email protected]
    GolangVersion: go1.13
    BuildStatus: Clean
    BuildTime: 2019-09-16--14:08:20
    

    服务无法启动,也没有相关的报错信息,请问应该如何正确的把文本模式下正常工具的namespace配置导入etcd呢?

  • SAVEPOINT 问题

    SAVEPOINT 问题

    'SQLSTATE[HY000]: General error: 1105 unknown error: get plan error, db: test_db, sql: SAVEPOINT LEVEL1, err: parse sql error, sql: SAVEPOINT LEVEL1, err: line 1 column 9 near "SAVEPOINT LEVEL1" The SQL being executed was: SAVEPOINT LEVEL1'

    image

  • 单机数据库,事务嵌套执行失败

    单机数据库,事务嵌套执行失败

    session error SQL, namespace: tp5_center_namespace_1, sql: SAVEPOINT LEVEL1, cost: 0 ms, err: get plan error, db: test_azmbk_db, sql: SAVEPOINT LEVEL1, err: parse sql error, sql: SAVEPOINT LEVEL1, err: line 1 column 9 near "SAVEPOINT LEVEL1"

  • 客户端重连后出现连接断开Broken pipe的异常

    客户端重连后出现连接断开Broken pipe的异常

    复现

    启动Gaea,使用MySQL客户端连接,然后重启Gaea,MySQL客户端执行show tables,MySQL客户端出现报错:

    mysql> show tables;
    ERROR 2006 (HY000): MySQL server has gone away
    No connection. Trying to reconnect...
    Connection id:    10007
    Current database: biz
    
    ERROR 2006 (HY000): MySQL server has gone away
    No connection. Trying to reconnect...
    Connection id:    10008
    Current database: biz
    
    ERROR 2006 (HY000): MySQL server has gone away
    mysql>
    
    

    查看Gaea日志,有broken pipe 的错误。

    [2021-05-20 18:58:08] [gaea_proxy] [mi-OptiPlex-7060] [WARN] [800000001] [github.com/XiaoMi/Gaea/proxy/server.(*Manager).RecordBackendSQLMetrics:manager.go:363] backend slow SQL, namespace: test_namespace_1, addr: 127.0.0.1:3308, sql: show tables, cost: 0 ms
    [2021-05-20 18:58:08] [gaea_proxy] [mi-OptiPlex-7060] [NOTICE] [800000001] Ignore broken pipe signal
    [2021-05-20 18:58:08] [gaea_proxy] [mi-OptiPlex-7060] [WARN] [800000001] [github.com/XiaoMi/Gaea/proxy/server.(*Session).Run:session.go:240] Session write response error, connId: 10008, err: Conn 10008: Write(header) failed: write tcp4 127.0.0.1:13306->127.0.0.1:41478: write: broken pipe
    [2021-05-20 18:58:08] [gaea_proxy] [mi-OptiPlex-7060] [DEBUG] [800000001] [github.com/XiaoMi/Gaea/proxy/server.(*Session).Close:session.go:195] client closed, 10008
    

    且出错后,其他查询都无法执行,比如select 1,报错同上。 退出MySQL客户端,重新登录,再次执行show tables,没有报错。

    原因

    抓包看可能是处理ComFieldList的返回包有问题,导致客户端自动断开。在将writeFieldList方法修改,不使用currentEphemeralBuffer后,问题修复。

  • ./bin/gaea 无法启动

    ./bin/gaea 无法启动

    执行./bin/gaea时候只显示info信息然后退出

    [root@dongrxin Gaea]# ./bin/gaea -config=etc/gaea.ini
    Build Version Information:Version: be1b26bff56a8dd7ce95a2bd0ee6c3c6b1496ce8-dirty
    GitRevision: be1b26bff56a8dd7ce95a2bd0ee6c3c6b1496ce8-dirty
    User: [email protected]
    GolangVersion: go1.14.12
    BuildStatus: Modified
    BuildTime: 2021-02-24--11:32:51
    
  • 应用报大量 “resource pool timed out”,大佬帮分析下原因。

    应用报大量 “resource pool timed out”,大佬帮分析下原因。

    昨天应用报大量“SQLSTATE[HY000]: General error: 1105 unknown error: resource pool timed out (SQL: xxxxxxxx”错误,我查看Gaea源码,发现 resource pool timed out 错误在 util\resource_pool.go的第36行定义。

    在这之前的一小段时间应用大量报" SQLSTATE[HY000]: General error: 1105 unknown error: Conn 0: Write(header) failed: write tcp 10.5.1.128:53996->10.0.8.48:3306: write: connection reset by peer (SQL:xxxxxxxxx"错误,在mysql/conn.go的402行发现 Write(header) failed:定义;与此同时Gaea日志中出现几十条"[shazam_proxy] [nicetuan-middle-payment-prod-002] [NOTICE] [900000001] [main.main.func1:main.go:90] Ignore broken pipe signal"。

    重启proxy后,应用恢复正常,而且这些日志只出现在一台应用服务器上(我把应用和proxy部署在同一台机器上),其它7台机器没事。 没弄明白这个问题出现的原因,麻烦大佬帮忙分析下。

  • prepare,exec方式代理导致decimal精度丢失

    prepare,exec方式代理导致decimal精度丢失

    客户端通过gaea代理访问后端数据库进行查询操作,如果使用prepare,exec方式进行操作,会导致精度丢失问题


    后端数据库版本:5.7.38 gaea版本:latest 客户端:go+gorm进行操作 数据库字段类型:decimal(58,18)


    通过gorm进行直接查询,结果符合预期

    
    type TestModel struct {
    	Amount decimal.Decimal `gorm:"type:decimal(58,18);"`
    }
    
    func (t TestModel) TableName() string {
    	return "table1"
    }
    
    func Test_GORM(t *testing.T) {
    	dsn := "user:123456@tcp(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local"
    	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    	if err != nil {
    		panic("failed to connect database")
    	}
    
    	tm := TestModel{}
    
    	db.Select("amount").Where("id = 10001").First(&tm)
    
    	fmt.Println(tm.Amount.String())
    }
    
    
    

    客户端打印的结果为

    11773175730.545026930000000051
    

    下面是通过gorm+prepare,exec方式进行查询

    
    func Test_GORMPrepare(t *testing.T) {
    	dsn := "user:123456@tcp(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local"
    	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    	if err != nil {
    		panic("failed to connect database")
    	}
    
    	tm := TestModel{}
    
    	db.Raw("select amount from table1 where id = ?", 10001).Scan(&tm)
    
    	fmt.Println(tm.Amount.String())
    }
    
    

    客户端打印的结果为

    11773175730.545027
    

    第二种方式使用prepare,exec方式进行执行查询,经过抓包和测试,发现后端返回给gaea是精确的,但是gaea对数据进行拼接的时候,转换为float,导致精度丢失

    导致问题的具体代码位置为 https://github.com/XiaoMi/Gaea/blob/master/mysql/result.go#L81

    大佬们帮忙解答下,是代码问题,还是使用方式不正确导致此问题

  • fix(sec): upgrade github.com/gin-gonic/gin to 1.7.7

    fix(sec): upgrade github.com/gin-gonic/gin to 1.7.7

    What happened?

    There are 1 security vulnerabilities found in github.com/gin-gonic/gin v1.7.2

    What did I do?

    Upgrade github.com/gin-gonic/gin from v1.7.2 to 1.7.7 for vulnerability fix

    What did you expect to happen?

    Ideally, no insecure libs should be used.

    The specification of the pull request

    PR Specification from OSCS

  • 执行批量更新时,Gaea代理会将SQL在结尾处添加个逗号,从而导致mysql底层执行失败。

    执行批量更新时,Gaea代理会将SQL在结尾处添加个逗号,从而导致mysql底层执行失败。

    mysql version:5.7.26-gaea mysql error message :error code [1105]; unknown error: get plan error

    update fs_container setcode= 'P510391227L00003',name= 'P510391227L00003',container_type_id= 3,structure_type= 'PALLET',use_type= 'GENERAL',container_state= 1,is_close= 0,task_id= 1,task_type= 'PICKING',task_no= 'PK2022072000000001',state= 1,date_code= null,factory_id= 1,warehouse_id= 254630,create_person= 696,update_person= 695,create_time= '2022-07-20 14:16:14',update_time` = null where id = 3;

                update fs_container set `code` = 'W510391227L00003',`name` = 'W510391227L00003', `container_type_id` = 2,`structure_type` = 'TURNOVERBOX',
                `use_type` = 'GENERAL',`container_state` = 1,`is_close` = 0,`task_id` = 1,`task_type` = 'PICKING',
                `task_no` = 'PK2022072000000001',`state` = 1,`date_code` = null,`factory_id` = 1,`warehouse_id` = 254630,`create_person` = 696,
                `update_person` = 695,`create_time` = '2022-07-20 14:16:42',`update_time` = null
                where id = 103, err: [parser:1149]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
    

    ; uncategorized SQLException; SQL state [HY000]; error code [1105]; unknown error: get plan error,`

  • prepare类型语句出错

    prepare类型语句出错

    用mysql官网的prepare语句测试 PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; SET @a = 3; SET @b = 4; EXECUTE stmt1 USING @a, @b; 报错如下: ERROR 1243 (HY000): Unknown prepared statement handler (stmt1) given to EXECUTE

mysql to mysql 轻量级多线程的库表数据同步

goMysqlSync golang mysql to mysql 轻量级多线程库表级数据同步 测试运行 设置当前binlog位置并且开始运行 go run main.go -position mysql-bin.000001 1 1619431429 查询当前binlog位置,参数n为秒数,查询结

Nov 15, 2022
A high-performance MySQL proxy

kingshard 中文主页 Overview kingshard is a high-performance proxy for MySQL powered by Go. Just like other mysql proxies, you can use it to split the read

Dec 30, 2022
MySQL proxy backups check recovery
MySQL proxy backups check recovery

一 、前言 感谢kingshard明星开源项目,本服务正是基于kingshard 开发而来。 本服务适用于相对封闭且经常断电的环境 针对此场景建议使用 MyISAM引擎。 在生产环境中我们数据库可能会遭遇各种各样的不测从而导致数据丢失,大概分为以下几种: 硬件故障 软件故障(目前生产环境经常发生的)

Oct 29, 2021
Goproxy4mysql - Kingshard- a high-performance proxy for MySQL powered by Go

kingshard 中文主页 Fork from github.com/flike/kingshard Overview kingshard is a high

Jan 7, 2022
a powerful mysql toolset with Go
a powerful mysql toolset with Go

go-mysql A pure go library to handle MySQL network protocol and replication. Call for Committer/Maintainer Sorry that I have no enough time to maintai

Dec 28, 2022
Sync MySQL data into elasticsearch
Sync MySQL data into elasticsearch

go-mysql-elasticsearch is a service syncing your MySQL data into Elasticsearch automatically. It uses mysqldump to fetch the origin data at first, the

Dec 30, 2022
Golang MySql binary log replication listener

Go MySql binary log replication listener Pure Go Implementation of MySQL replication protocol. This allow you to receive event like insert, update, de

Oct 25, 2022
MySQL replication topology management and HA
MySQL replication topology management and HA

orchestrator [Documentation] orchestrator is a MySQL high availability and replication management tool, runs as a service and provides command line ac

Jan 4, 2023
Vitess is a database clustering system for horizontal scaling of MySQL.

Vitess Vitess is a database clustering system for horizontal scaling of MySQL through generalized sharding. By encapsulating shard-routing logic, Vite

Jan 3, 2023
db-recovery is a tool for recovering MySQL data.

db-recovery is a tool for recovering MySQL data. It is used in scenarios where the database has no backup or binlog. It can parse data files and redo/undo logs to recover data.

Nov 17, 2022
一个使 mysql,pgsql 数据库表自动生成 go struct 的工具

db2go 一个使 mysql、pgsql 数据库表自动生成 go struct 的工具 快速使用 将项目放入到GOPATH/src目录下

Nov 25, 2022
🐳 A most popular sql audit platform for mysql
🐳 A most popular sql audit platform for mysql

?? A most popular sql audit platform for mysql

Jan 6, 2023
Dumpling is a fast, easy-to-use tool written by Go for dumping data from the database(MySQL, TiDB...) to local/cloud(S3, GCP...) in multifarious formats(SQL, CSV...).

?? Dumpling Dumpling is a tool and a Go library for creating SQL dump from a MySQL-compatible database. It is intended to replace mysqldump and mydump

Nov 9, 2022
Vitess is a database clustering system for horizontal scaling of MySQL.

Vitess Vitess is a database clustering system for horizontal scaling of MySQL through generalized sharding. By encapsulating shard-routing logic, Vite

Jan 4, 2023
GitHub's Online Schema Migrations for MySQL
GitHub's Online Schema Migrations for MySQL

gh-ost GitHub's online schema migration for MySQL gh-ost is a triggerless online schema migration solution for MySQL. It is testable and provides paus

Jan 4, 2023
Bifrost ---- 面向生产环境的 MySQL 同步到Redis,MongoDB,ClickHouse,MySQL等服务的异构中间件
Bifrost ---- 面向生产环境的 MySQL 同步到Redis,MongoDB,ClickHouse,MySQL等服务的异构中间件

Bifrost ---- 面向生产环境的 MySQL 同步到Redis,ClickHouse等服务的异构中间件 English 漫威里的彩虹桥可以将 雷神 送到 阿斯加德 和 地球 而这个 Bifrost 可以将 你 MySQL 里的数据 全量 , 实时的同步到 : Redis MongoDB Cl

Dec 30, 2022
go mysql driver, support distributed transaction

Go-MySQL-Driver A MySQL-Driver for Go's database/sql package Features Requirements Installation Usage DSN (Data Source Name) Password Protocol Address

Jul 23, 2022
A MySQL-compatible relational database with a storage agnostic query engine. Implemented in pure Go.

go-mysql-server go-mysql-server is a SQL engine which parses standard SQL (based on MySQL syntax) and executes queries on data sources of your choice.

Jan 2, 2023