{"id":37196161,"url":"https://github.com/layerxcom/go-mysql","last_synced_at":"2026-01-14T22:49:10.638Z","repository":{"id":189759095,"uuid":"681232503","full_name":"LayerXcom/go-mysql","owner":"LayerXcom","description":"a powerful mysql toolset with Go","archived":false,"fork":true,"pushed_at":"2024-04-26T04:56:37.000Z","size":2693,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2024-04-26T05:38:24.231Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"go-mysql-org/go-mysql","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LayerXcom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-21T14:59:53.000Z","updated_at":"2024-04-26T05:38:24.232Z","dependencies_parsed_at":"2023-08-21T17:11:58.630Z","dependency_job_id":null,"html_url":"https://github.com/LayerXcom/go-mysql","commit_stats":null,"previous_names":["layerxcom/go-mysql"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/LayerXcom/go-mysql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerXcom%2Fgo-mysql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerXcom%2Fgo-mysql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerXcom%2Fgo-mysql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerXcom%2Fgo-mysql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LayerXcom","download_url":"https://codeload.github.com/LayerXcom/go-mysql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LayerXcom%2Fgo-mysql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28436903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T22:49:09.964Z","updated_at":"2026-01-14T22:49:10.629Z","avatar_url":"https://github.com/LayerXcom.png","language":"Go","funding_links":["https://paypal.me/siddontang"],"categories":[],"sub_categories":[],"readme":"# go-mysql\n\nA pure go library to handle MySQL network protocol and replication.\n\n![semver](https://img.shields.io/github/v/tag/go-mysql-org/go-mysql)\n![example workflow](https://github.com/go-mysql-org/go-mysql/actions/workflows/ci.yml/badge.svg)\n![gomod version](https://img.shields.io/github/go-mod/go-version/go-mysql-org/go-mysql/master)\n\n## How to migrate to this repo\nTo change the used package in your repo it's enough to add this `replace` directive to your `go.mod`:\n```\nreplace github.com/siddontang/go-mysql =\u003e github.com/go-mysql-org/go-mysql v1.7.0\n```\n\nv1.7.0 - is the last tag in repo, feel free to choose what you want.\n\n## Changelog\nThis repo uses [Changelog](CHANGELOG.md).\n\n---\n# Content\n* [Replication](#replication)\n* [Incremental dumping](#canal)\n* [Client](#client)\n* [Fake server](#server)\n* [Failover](#failover)\n* [database/sql like driver](#driver)\n\n## Replication\n\nReplication package handles MySQL replication protocol like [python-mysql-replication](https://github.com/noplay/python-mysql-replication).\n\nYou can use it as a MySQL replica to sync binlog from master then do something, like updating cache, etc...\n\n### Example\n\n```go\nimport (\n\t\"github.com/go-mysql-org/go-mysql/replication\"\n\t\"os\"\n)\n// Create a binlog syncer with a unique server id, the server id must be different from other MySQL's. \n// flavor is mysql or mariadb\ncfg := replication.BinlogSyncerConfig {\n\tServerID: 100,\n\tFlavor:   \"mysql\",\n\tHost:     \"127.0.0.1\",\n\tPort:     3306,\n\tUser:     \"root\",\n\tPassword: \"\",\n}\nsyncer := replication.NewBinlogSyncer(cfg)\n\n// Start sync with specified binlog file and position\nstreamer, _ := syncer.StartSync(mysql.Position{binlogFile, binlogPos})\n\n// or you can start a gtid replication like\n// streamer, _ := syncer.StartSyncGTID(gtidSet)\n// the mysql GTID set likes this \"de278ad0-2106-11e4-9f8e-6edd0ca20947:1-2\"\n// the mariadb GTID set likes this \"0-1-100\"\n\nfor {\n\tev, _ := streamer.GetEvent(context.Background())\n\t// Dump event\n\tev.Dump(os.Stdout)\n}\n\n// or we can use a timeout context\nfor {\n\tctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)\n\tev, err := streamer.GetEvent(ctx)\n\tcancel()\n\n\tif err == context.DeadlineExceeded {\n\t\t// meet timeout\n\t\tcontinue\n\t}\n\n\tev.Dump(os.Stdout)\n}\n```\n\nThe output looks:\n\n```\n=== RotateEvent ===\nDate: 1970-01-01 08:00:00\nLog position: 0\nEvent size: 43\nPosition: 4\nNext log name: mysql.000002\n\n=== FormatDescriptionEvent ===\nDate: 2014-12-18 16:36:09\nLog position: 120\nEvent size: 116\nVersion: 4\nServer version: 5.6.19-log\nCreate date: 2014-12-18 16:36:09\n\n=== QueryEvent ===\nDate: 2014-12-18 16:38:24\nLog position: 259\nEvent size: 139\nSalve proxy ID: 1\nExecution time: 0\nError code: 0\nSchema: test\nQuery: DROP TABLE IF EXISTS `test_replication` /* generated by server */\n```\n\n## Canal \n\nCanal is a package that can sync your MySQL into everywhere, like Redis, Elasticsearch. \n\nFirst, canal will dump your MySQL data then sync changed data using binlog incrementally. \n\nYou must use ROW format for binlog, full binlog row image is preferred, because we may meet some errors when primary key changed in update for minimal or noblob row image. \n\nA simple example:\n\n```go\npackage main\n\nimport (\n\t\"github.com/go-mysql-org/go-mysql/canal\"\n\t\"github.com/siddontang/go-log/log\"\n)\n\ntype MyEventHandler struct {\n\tcanal.DummyEventHandler\n}\n\nfunc (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {\n\tlog.Infof(\"%s %v\\n\", e.Action, e.Rows)\n\treturn nil\n}\n\nfunc (h *MyEventHandler) String() string {\n\treturn \"MyEventHandler\"\n}\n\nfunc main() {\n\tcfg := canal.NewDefaultConfig()\n\tcfg.Addr = \"127.0.0.1:3306\"\n\tcfg.User = \"root\"\n\t// We only care table canal_test in test db\n\tcfg.Dump.TableDB = \"test\"\n\tcfg.Dump.Tables = []string{\"canal_test\"}\n\n\tc, err := canal.NewCanal(cfg)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Register a handler to handle RowsEvent\n\tc.SetEventHandler(\u0026MyEventHandler{})\n\n\t// Start canal\n\tc.Run()\n}\n```\n\nYou can see [go-mysql-elasticsearch](https://github.com/siddontang/go-mysql-elasticsearch) for how to sync MySQL data into Elasticsearch. \n\n## Client\n\nClient package supports a simple MySQL connection driver which you can use it to communicate with MySQL server. \n\n### Example\n\n```go\nimport (\n\t\"github.com/go-mysql-org/go-mysql/client\"\n)\n\n// Connect MySQL at 127.0.0.1:3306, with user root, an empty password and database test\nconn, _ := client.Connect(\"127.0.0.1:3306\", \"root\", \"\", \"test\")\n\n// Or to use SSL/TLS connection if MySQL server supports TLS\n//conn, _ := client.Connect(\"127.0.0.1:3306\", \"root\", \"\", \"test\", func(c *Conn) {c.UseSSL(true)})\n\n// Or to set your own client-side certificates for identity verification for security\n//tlsConfig := NewClientTLSConfig(caPem, certPem, keyPem, false, \"your-server-name\")\n//conn, _ := client.Connect(\"127.0.0.1:3306\", \"root\", \"\", \"test\", func(c *Conn) {c.SetTLSConfig(tlsConfig)})\n\nconn.Ping()\n\n// Insert\nr, _ := conn.Execute(`insert into table (id, name) values (1, \"abc\")`)\n\n// Get last insert id\nprintln(r.InsertId)\n// Or affected rows count\nprintln(r.AffectedRows)\n\n// Select\nr, err := conn.Execute(`select id, name from table where id = 1`)\n\n// Close result for reuse memory (it's not necessary but very useful)\ndefer r.Close()\n\n// Handle resultset\nv, _ := r.GetInt(0, 0)\nv, _ = r.GetIntByName(0, \"id\")\n\n// Direct access to fields\nfor _, row := range r.Values {\n\tfor _, val := range row {\n\t\t_ = val.Value() // interface{}\n\t\t// or\n\t\tif val.Type == mysql.FieldValueTypeFloat {\n\t\t\t_ = val.AsFloat64() // float64\n\t\t}\n\t}   \n}\n```\n\nTested MySQL versions for the client include:\n- 5.5.x\n- 5.6.x\n- 5.7.x\n- 8.0.x\n\n### Example for SELECT streaming (v1.1.1)\nYou can use also streaming for large SELECT responses.\nThe callback function will be called for every result row without storing the whole resultset in memory.\n`result.Fields` will be filled before the first callback call.\n\n```go\n// ...\nvar result mysql.Result\nerr := conn.ExecuteSelectStreaming(`select id, name from table LIMIT 100500`, \u0026result, func(row []mysql.FieldValue) error {\n    for idx, val := range row {\n    \tfield := result.Fields[idx]\n    \t// You must not save FieldValue.AsString() value after this callback is done.\n    \t// Copy it if you need.\n    \t// ...\n    }\n    return nil\n}, nil)\n\n// ...\n```\n\n### Example for connection pool (v1.3.0)\n\n```go\nimport (\n    \"github.com/go-mysql-org/go-mysql/client\"\n)\n\npool := client.NewPool(log.Debugf, 100, 400, 5, \"127.0.0.1:3306\", `root`, ``, `test`)\n// ...\nconn, _ := pool.GetConn(ctx)\ndefer pool.PutConn(conn)\n\nconn.Execute() / conn.Begin() / etc...\n```\n\n## Server\n\nServer package supplies a framework to implement a simple MySQL server which can handle the packets from the MySQL client. \nYou can use it to build your own MySQL proxy. The server connection is compatible with MySQL 5.5, 5.6, 5.7, and 8.0 versions,\nso that most MySQL clients should be able to connect to the Server without modifications.\n\n### Example\n\nMinimalistic MySQL server implementation:\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"net\"\n\n\t\"github.com/go-mysql-org/go-mysql/server\"\n)\n\nfunc main() {\n\t// Listen for connections on localhost port 4000\n\tl, err := net.Listen(\"tcp\", \"127.0.0.1:4000\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Accept a new connection once\n\tc, err := l.Accept()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Create a connection with user root and an empty password.\n\t// You can use your own handler to handle command here.\n\tconn, err := server.NewConn(c, \"root\", \"\", server.EmptyHandler{})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// as long as the client keeps sending commands, keep handling them\n\tfor {\n\t\tif err := conn.HandleCommand(); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n}\n\n```\n\nAnother shell\n\n```\n$ mysql -h127.0.0.1 -P4000 -uroot\nYour MySQL connection id is 10001\nServer version: 5.7.0\n\nMySQL [(none)]\u003e\n// Since EmptyHandler implements no commands, it will throw an error on any query that you will send\n```\n\n\u003e ```NewConn()``` will use default server configurations:\n\u003e 1. automatically generate default server certificates and enable TLS/SSL support.\n\u003e 2. support three mainstream authentication methods **'mysql_native_password'**, **'caching_sha2_password'**, and **'sha256_password'**\n\u003e    and use **'mysql_native_password'** as default.\n\u003e 3. use an in-memory user credential provider to store user and password.\n\u003e\n\u003e To customize server configurations, use ```NewServer()``` and create connection via ```NewCustomizedConn()```.\n\n\n## Failover\n\nFailover supports to promote a new master and let replicas replicate from it automatically when the old master was down.\n\nFailover supports MySQL \u003e= 5.6.9 with GTID mode, if you use lower version, e.g, MySQL 5.0 - 5.5, please use [MHA](http://code.google.com/p/mysql-master-ha/) or [orchestrator](https://github.com/outbrain/orchestrator).\n\nAt the same time, Failover supports MariaDB \u003e= 10.0.9 with GTID mode too. \n\nWhy only GTID? Supporting failover with no GTID mode is very hard, because replicas can not find the proper binlog filename and position with the new master.\nAlthough there are many companies use MySQL 5.0 - 5.5, I think upgrade MySQL to 5.6 or higher is easy. \n\n## Driver\n\nDriver is the package that you can use go-mysql with go database/sql like other drivers. A simple example:\n\n```go\npackage main\n\nimport (\n\t\"database/sql\"\n\n\t_ \"github.com/go-mysql-org/go-mysql/driver\"\n)\n\nfunc main() {\n\t// dsn format: \"user:password@addr?dbname\"\n\tdsn := \"root@127.0.0.1:3306?test\"\n\tdb, _ := sql.Open(dsn)\n\tdb.Close()\n}\n```\n\nWe pass all tests in https://github.com/bradfitz/go-sql-test using go-mysql driver. :-)\n\n## Donate\n\nIf you like the project and want to buy me a cola, you can through: \n\n|PayPal|微信|\n|------|---|\n|[![](https://www.paypalobjects.com/webstatic/paypalme/images/pp_logo_small.png)](https://paypal.me/siddontang)|[![](https://github.com/siddontang/blog/blob/master/donate/weixin.png)|\n\n## Feedback\n\ngo-mysql is still in development, your feedback is very welcome. \n\n\nGmail: siddontang@gmail.com\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flayerxcom%2Fgo-mysql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flayerxcom%2Fgo-mysql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flayerxcom%2Fgo-mysql/lists"}