{"id":13412579,"url":"https://github.com/sanketplus/go-mysql-lock","last_synced_at":"2025-05-14T06:32:59.634Z","repository":{"id":48932322,"uuid":"270038252","full_name":"sanketplus/go-mysql-lock","owner":"sanketplus","description":"MySQL Backed Locking Primitive","archived":false,"fork":false,"pushed_at":"2024-05-13T18:29:44.000Z","size":23,"stargazers_count":61,"open_issues_count":2,"forks_count":14,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-07-31T20:51:08.513Z","etag":null,"topics":["distributed-lock","go","golang","lock","mysql","mysql-lock"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sanketplus.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-06T16:30:07.000Z","updated_at":"2024-06-26T06:20:14.000Z","dependencies_parsed_at":"2024-05-13T19:43:47.590Z","dependency_job_id":"152a2b24-0d3f-45c1-92c6-cc0dff6d48ca","html_url":"https://github.com/sanketplus/go-mysql-lock","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanketplus%2Fgo-mysql-lock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanketplus%2Fgo-mysql-lock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanketplus%2Fgo-mysql-lock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanketplus%2Fgo-mysql-lock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sanketplus","download_url":"https://codeload.github.com/sanketplus/go-mysql-lock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225280754,"owners_count":17449217,"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":["distributed-lock","go","golang","lock","mysql","mysql-lock"],"created_at":"2024-07-30T20:01:26.392Z","updated_at":"2024-11-19T01:52:08.929Z","avatar_url":"https://github.com/sanketplus.png","language":"Go","funding_links":[],"categories":["Distributed Systems","分布式系统","Relational Databases"],"sub_categories":["Search and Analytic Databases","SQL 查询语句构建库","Advanced Console UIs","检索及分析资料库"],"readme":"# go-mysql-lock\n[![GoDoc](https://godoc.org/github.com/sanketplus/go-mysql-lock?status.svg)](https://godoc.org/github.com/sanketplus/go-mysql-lock)\n[![Azure DevOps builds](https://img.shields.io/azure-devops/build/sanketplus/go-mysql-lock/1)](https://dev.azure.com/sanketplus/go-mysql-lock/_build?definitionId=1)\n[![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/sanketplus/go-mysql-lock/1)](https://dev.azure.com/sanketplus/go-mysql-lock/_build?definitionId=1)\n[![Go Report Card](https://goreportcard.com/badge/github.com/sanketplus/go-mysql-lock)](https://goreportcard.com/report/github.com/sanketplus/go-mysql-lock)\n\ngo-mysql-lock provides locking primitive based on MySQL's [GET_LOCK](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html#function_get-lock)\nLock names are strings and MySQL enforces a maximum length on lock names of 64 characters.\n\n## Use cases\nThough there are mature locking primitives provided by systems like Zookeeper and etcd, when you have an application which\nis primarily dependent on MySQL for its uptime and health, added resiliency provided by systems just mentioned doesn't add\nmuch benefit. go-mysql-lock helps when you have multiple application instances which are backed by a common mysql instance\nand you want only one of those application instances to hold a lock and do certain tasks.\n\n#### Installation\n```$bash\ngo get github.com/sanketplus/go-mysql-lock\n```\n\n### Example:\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"database/sql\"\n    \n    _ \"github.com/go-sql-driver/mysql\"\n    \"github.com/sanketplus/go-mysql-lock\"\n)\n\nfunc main() {\n\tdb, _ := sql.Open(\"mysql\", \"root@tcp(localhost:3306)/dyno_test\")\n\n\tlocker := gomysqllock.NewMysqlLocker(db)\n\n\tlock, _ := locker.Obtain(\"foo\")\n\tlock.Release()\n}\n```\n\n## Features\n#### Customizable Refresh Period\nOnce the lock is obtained, a goroutine periodically (default every 1 second) keeps pinging on connection since the lock\nis valid on a connection(session). To configure the refresh interval\n```go\nlocker := gomysqllock.NewMysqlLocker(db, gomysqllock.WithRefreshInterval(time.Millisecond*500))\n```\n\n#### Obtain Lock With Context\nBy default, an attempt to obtain a lock is backed by background context. That means the `Obtain` call would block\nindefinitely. Optionally, an `Obtain` call can be made with user given context which will get cancelled with the given\ncontext.\n\nThe following call will give up after a second if the lock was not obtained.\n```go\nlocker := gomysqllock.NewMysqlLocker(db)\nctxShort, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Second))\nlock, err := locker.ObtainContext(ctxShort, \"key\")\n```\n\n#### Obtain Lock With (MySQL) Timeout\nMySQL has the ability to timeout and return if the lock can't be acquired in a given number of seconds.\nThis timeout can be specified when using `ObtainTimeout` and `ObtainTimeoutContext`. On timeout, `ErrMySQLTimeout` is returned, and the lock is not obtained.\n\nThe following call will give up after a second if the lock was not obtained, using MySQL timeout option:\n```go\nlocker := gomysqllock.NewMysqlLocker(db)\nlock, err := locker.ObtainTimeout(\"key\", 1)\n```\n\n#### Know When The Lock is Lost\nObtained lock has a context which is cancelled if the lock is lost. This is determined while a goroutine keeps pinging the connection. If there is an error while pinging, assuming connection has an error, the context is cancelled. And the lock owner gets notified of the lost lock.\n```go\ncontext := lock.GetContext()\n``` \n\n### Compatibility\n\nThis library is tested (automatically) against MySQL 8 and MariaDB 10.1, and it should work for MariaDB versions \u003e= 10.1, MySQL versions \u003e= 5.6, and Vitess versions \u003e= 15.0.\n\nNote that `GET_LOCK` function won't lock indefinitely on MariaDB 10.1 / MySQL 5.6 and older, as `0` or negative value for timeouts are not accepted in those versions. This means that **in MySQL \u003c= 5.6 / MariaDB \u003c= 10.1 you can't use `Obtain` or `ObtainContext`**. To achieve a similar goal, you can use `ObtainTimeout` (and `ObtainTimeoutContext`) using a very high timeout value.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanketplus%2Fgo-mysql-lock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsanketplus%2Fgo-mysql-lock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanketplus%2Fgo-mysql-lock/lists"}