{"id":13412095,"url":"https://github.com/go-mysql-org/go-mysql","last_synced_at":"2025-05-12T05:21:44.035Z","repository":{"id":14332868,"uuid":"17042400","full_name":"go-mysql-org/go-mysql","owner":"go-mysql-org","description":"a powerful mysql toolset with Go","archived":false,"fork":false,"pushed_at":"2025-05-08T11:30:35.000Z","size":3430,"stargazers_count":4736,"open_issues_count":153,"forks_count":1021,"subscribers_count":157,"default_branch":"master","last_synced_at":"2025-05-11T03:04:05.598Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-mysql-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-02-21T01:56:45.000Z","updated_at":"2025-05-09T08:45:46.000Z","dependencies_parsed_at":"2023-10-12T12:58:04.246Z","dependency_job_id":"3918c988-5b8a-4d9d-9212-37eca8cd6daf","html_url":"https://github.com/go-mysql-org/go-mysql","commit_stats":{"total_commits":817,"total_committers":190,"mean_commits":4.3,"dds":0.7233782129742963,"last_synced_commit":"d02e79aea163459997784240e0e8bcf0deb3535b"},"previous_names":["siddontang/go-mysql"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-mysql-org%2Fgo-mysql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-mysql-org%2Fgo-mysql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-mysql-org%2Fgo-mysql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-mysql-org%2Fgo-mysql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-mysql-org","download_url":"https://codeload.github.com/go-mysql-org/go-mysql/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253509778,"owners_count":21919588,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2024-07-30T20:01:20.930Z","updated_at":"2025-05-11T03:04:16.907Z","avatar_url":"https://github.com/go-mysql-org.png","language":"Go","funding_links":[],"categories":["Go","Drivers","Database","Generators","Toolkits","Uncategorized"],"sub_categories":["Database Tools"],"readme":"# go-mysql\n\nA pure Go library to handle MySQL network protocol and replication as used by MySQL and MariaDB.\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[![Go Reference](https://pkg.go.dev/badge/github.com/go-mysql-org/go-mysql.svg)](https://pkg.go.dev/github.com/go-mysql-org/go-mysql)\n\n## Platform Support\n\nAs a pure Go library, this project follows [Go's minimum requirements](https://go.dev/wiki/MinimumRequirements).\n\nThis library has been tested or deployed on the following operating systems and architectures:\n\n| Operating System | Architecture | Runtime Supported | CI | Notes                                                                                                                          |\n|------------------|--------------|-------------------|----|--------------------------------------------------------------------------------------------------------------------------------|\n| Linux            | amd64        | ✅                | ✅ | Check GitHub Actions of this project.                                                                                          |\n| Linux            | s390x        | ✅                | ✅ | A daily CI runs on an s390x VM, supported by the [IBM Z and LinuxONE Community](https://www.ibm.com/community/z/open-source/). |\n| Linux            | arm64        | ✅                | ❌ | Deployed in a production environment of a user.                                                                                |\n| Linux            | arm          | ✅                | ❌ | A test in CI to make sure builds for 32-bits platforms work.                                                                   |\n| FreeBSD          | amd64        | ✅                | ❌ | Sporadically tested by developers.                                                                                             |\n\nOther platforms supported by Go may also work, but they have not been verified. Feel free to report your test results.\n\nThis library is not compatible with [TinyGo](https://tinygo.org/).\n\n## Changelog\n\nThis library uses [Changelog](CHANGELOG.md).\n\n---\n# Content\n* [Replication](#replication) - Process events from a binlog stream.\n* [Incremental dumping](#canal) - Sync from MySQL to Redis, Elasticsearch, etc.\n* [Client](#client) - Simple MySQL client.\n* [Fake server](#server) - server side of the MySQL protocol, as library.\n* [database/sql like driver](#driver) - An alternative `database/sql` driver for MySQL.\n* [Logging](#logging) - Custom logging options.\n* [Migration](#how-to-migrate-to-this-repo) - Information for how to migrate if you used the old location of this project.\n\n## Examples\n\nThe `cmd` directory contains example applications that can be build by running `make build` in the root of the project. The resulting binaries will be places in `bin/`.\n\n- `go-binlogparser`: parses a binlog file at a given offset\n- `go-canal`: streams binlog events from a server to canal\n- `go-mysqlbinlog`: streams binlog events\n- `go-mysqldump`: like `mysqldump`, but in Go\n- `go-mysqlserver`: fake MySQL server\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// gtidSet, _ := mysql.ParseGTIDSet(mysql.MySQLFlavor, \"de278ad0-2106-11e4-9f8e-6edd0ca20947:1-2\")\n// streamer, _ := syncer.StartSyncGTID(gtidSet)\n// the mysql GTID set is like this \"de278ad0-2106-11e4-9f8e-6edd0ca20947:1-2\" and uses mysql.MySQLFlavor\n// the mariadb GTID set is like this \"0-1-100\" and uses mysql.MariaDBFlavor\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)\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/go-mysql-org/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\nFor an example see [`example_client_test.go`](client/example_client_test.go). You can run this testable example with \n`go test -v ./client -run Example`.\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\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## 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(\"mysql\", dsn)\n\tdb.Close()\n}\n```\n\n### Driver Options\n\nConfiguration options can be provided by the standard DSN (Data Source Name).\n\n```\n[user[:password]@]addr[/db[?param=X]]\n```\n\n#### `collation`\n\nSet a collation during the Auth handshake.\n\n| Type      | Default         | Example                                               |\n| --------- | --------------- | ----------------------------------------------------- |\n| string    | utf8_general_ci | user:pass@localhost/mydb?collation=latin1_general_ci  |\n\n#### `compress`\n\nEnable compression between the client and the server. Valid values are 'zstd','zlib','uncompressed'.\n\n| Type      | Default       | Example                                 |\n| --------- | ------------- | --------------------------------------- |\n| string    | uncompressed  | user:pass@localhost/mydb?compress=zlib  |\n\n#### `readTimeout`\n\nI/O read timeout. The time unit is specified in the argument value using\ngolang's [ParseDuration](https://pkg.go.dev/time#ParseDuration) format.\n\n0 means no timeout.\n\n| Type      | Default   | Example                                     |\n| --------- | --------- | ------------------------------------------- |\n| duration  | 0         | user:pass@localhost/mydb?readTimeout=10s    |\n\n#### `ssl`\n\nEnable TLS between client and server. Valid values are `true` or `custom`. When using `custom`,\nthe connection will use the TLS configuration set by SetCustomTLSConfig matching the host.\n\n| Type      | Default   | Example                                     |\n| --------- | --------- | ------------------------------------------- |\n| string    |           | user:pass@localhost/mydb?ssl=true           |\n\n#### `timeout`\n\nTimeout is the maximum amount of time a dial will wait for a connect to complete.\nThe time unit is specified in the argument value using golang's [ParseDuration](https://pkg.go.dev/time#ParseDuration) format.\n\n0 means no timeout.\n\n| Type      | Default   | Example                                     |\n| --------- | --------- | ------------------------------------------- |\n| duration  | 0         | user:pass@localhost/mydb?timeout=1m         |\n\n#### `writeTimeout`\n\nI/O write timeout. The time unit is specified in the argument value using\ngolang's [ParseDuration](https://pkg.go.dev/time#ParseDuration) format.\n\n0 means no timeout.\n\n| Type      | Default   | Example                                         |\n| --------- | --------- | ----------------------------------------------- |\n| duration  | 0         | user:pass@localhost/mydb?writeTimeout=1m30s     |\n\n#### `retries`\n\nAllows disabling the golang `database/sql` default behavior to retry errors\nwhen `ErrBadConn` is returned by the driver. When retries are disabled\nthis driver will not return `ErrBadConn` from the `database/sql` package.\n\nValid values are `on` (default) and `off`.\n\n| Type      | Default   | Example                                         |\n| --------- | --------- | ----------------------------------------------- |\n| string    | on        | user:pass@localhost/mydb?retries=off            |\n\n### Custom Driver Options\n\nThe driver package exposes the function `SetDSNOptions`, allowing for modification of the\nconnection by adding custom driver options.\nIt requires a full import of the driver (not by side-effects only).\n\nExample of defining a custom option:\n\n```golang\nimport (\n \"database/sql\"\n\n \"github.com/go-mysql-org/go-mysql/driver\"\n)\n\nfunc main() {\n driver.SetDSNOptions(map[string]DriverOption{\n  \"no_metadata\": func(c *client.Conn, value string) error {\n   c.SetCapability(mysql.CLIENT_OPTIONAL_RESULTSET_METADATA)\n   return nil\n  },\n })\n\n // dsn format: \"user:password@addr/dbname?\"\n dsn := \"root@127.0.0.1:3306/test?no_metadata=true\"\n db, _ := sql.Open(dsn)\n db.Close()\n}\n```\n\n### Custom Driver Name\n\nA custom driver name can be set via build options: `-ldflags '-X \"github.com/go-mysql-org/go-mysql/driver.driverName=gomysql\"'`.\n\nThis can be useful when using [GORM](https://gorm.io/docs/connecting_to_the_database.html#Customize-Driver):\n\n```go\nimport (\n  _ \"github.com/go-mysql-org/go-mysql/driver\"\n  \"gorm.io/driver/mysql\"\n  \"gorm.io/gorm\"\n)\n\ndb, err := gorm.Open(mysql.New(mysql.Config{\n  DriverName: \"gomysql\",\n  DSN: \"gorm:gorm@127.0.0.1:3306/test\",\n}))\n```\n\n### Custom NamedValueChecker\n\nGolang allows for custom handling of query arguments before they are passed to the driver\nwith the implementation of a [NamedValueChecker](https://pkg.go.dev/database/sql/driver#NamedValueChecker). By doing a full import of the driver (not by side-effects only),\na custom NamedValueChecker can be implemented.\n\n```golang\nimport (\n \"database/sql\"\n\n \"github.com/go-mysql-org/go-mysql/driver\"\n)\n\nfunc main() {\n driver.AddNamedValueChecker(func(nv *sqlDriver.NamedValue) error {\n  rv := reflect.ValueOf(nv.Value)\n  if rv.Kind() != reflect.Uint64 {\n   // fallback to the default value converter when the value is not a uint64\n   return sqlDriver.ErrSkip\n  }\n\n  return nil\n })\n\n conn, err := sql.Open(\"mysql\", \"root@127.0.0.1:3306/test\")\n defer conn.Close()\n\n stmt, err := conn.Prepare(\"select * from table where id = ?\")\n defer stmt.Close()\n var val uint64 = math.MaxUint64\n // without the NamedValueChecker this query would fail\n result, err := stmt.Query(val)\n}\n```\n\n\nWe pass all tests in https://github.com/bradfitz/go-sql-test using go-mysql driver. :-)\n\n## Logging\n\nLogging uses [log/slog](https://pkg.go.dev/log/slog) and by default is sent to standard out.\n\nFor the old logging package `github.com/siddontang/go-log/log`, a converting package \n`https://github.com/serprex/slog-siddontang` is available.\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.12.0\n```\n\nThis can be done by running this command:\n```\ngo mod edit -replace=github.com/siddontang/go-mysql=github.com/go-mysql-org/go-mysql@v1.12.0\n```\n\nv1.12.0 - is the last tag in repo, feel free to choose what you want.\n\n## Credits\n\ngo-mysql was started by @siddontang and has many [contributors](https://github.com/go-mysql-org/go-mysql/graphs/contributors)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-mysql-org%2Fgo-mysql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-mysql-org%2Fgo-mysql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-mysql-org%2Fgo-mysql/lists"}