在使用 MySQL 时,避免死锁是一项重要的任务。死锁通常发生在多个事务相互等待对方持有的锁时,导致无法继续执行。
下面是一个使用 Go 和 MySQL 的示例,展示了如何避免死锁以及捕获和处理死锁错误:
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
// 连接到 MySQL
dsn := "user:password@tcp(127.0.0.1:3306)/dbname"
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 确保连接成功
if err := db.Ping(); err != nil {
log.Fatal(err)
}
// 执行事务
if err := executeTransaction(db); err != nil {
log.Printf("Transaction failed: %v", err)
}
}
func executeTransaction(db *sql.DB) error {
var err error
for i := 0; i < 5; i++ { // 重试最多 5 次
tx, err := db.Begin()
if err != nil {
return err
}
// 执行查询或更新操作
_, err = tx.Exec("UPDATE table1 SET value1 = value1 + 1 WHERE id = 1")
if err != nil {
tx.Rollback()
return err
}
_, err = tx.Exec("UPDATE table2 SET value2 = value2 - 1 WHERE id = 1")
if err != nil {
tx.Rollback()
return err
}
// 提交事务
err = tx.Commit()
if err == nil {
return nil // 成功
}
// 检查是否为死锁错误
if isDeadlockError(err) {
log.Printf("Deadlock detected, retrying... (%d/5)", i+1)
time.Sleep(time.Second) // 等待一段时间后重试
continue
}
// 其他错误
return err
}
return fmt.Errorf("transaction failed after 5 retries: %v", err)
}
func isDeadlockError(err error) bool {
if mysqlErr, ok := err.(*mysql.MySQLError); ok {
// Error code 1213: Deadlock found when trying to get lock; try restarting transaction
return mysqlErr.Number == 1213
}
return false
}原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。