[当我使用golang查询mysql时,有时我在代码中发现“ deadlock err”。
我的问题不是“为什么发生死锁”,而是为什么在“ err = rows.Err()”中发现死锁err。在我看来,如果发生死锁,我应该在“ tx.Query”的返回错误中得到它。
这是演示代码,“点2”是发生死锁错误的位置
func demoFunc(tx *sql.Tx, arg1, arg2 int) ([]outItem, error) {
var ret []outItem
var err error
var rows *sql.Rows
//xxxLockSql may deadlock, so try again for 3-times
for i := 0; i < 3; i++ {
//------ point 1
rows, err = tx.Query(xxxLockSql, arg1, arg2)
if err == nil {
break
}
log.Printf("[ERROR] xxxLockSql failed, err %s, retry %d", err.Error(), i)
time.Sleep(time.Millisecond * 10)
}
//if query xxxLockSql failed up to 3-times, then return
if err != nil {
log.Printf("[ERROR] xxxLockSql failed, err %s", err.Error())
return ret, err
}
defer rows.Close()
for rows.Next() {
err = rows.Scan(&a1, &a2)
if err != nil {
return ret, err
}
ret = append(ret, acl)
}
//------ point 2
if err = rows.Err(); err != nil {
// i found deadlock err in this "if" segment.
// err content is "Error 1213: Deadlock found when trying to get lock; try restarting transaction"
log.Printf("[ERROR] loop rows failed, err %s", err.Error())
return ret, err
}
return ret, nil
}
我不确定原因,因为您没有提到数据库驱动程序(以及您使用的是哪个sql
软件包)。但是我认为这是因为sql.Query
是惰性的,这意味着查询和加载行被推迟到实际使用为止,即rows.Next()
-这就是在那里发生死锁错误的原因。
由于它为什么不在循环中,是因为当发生错误时,rows.Next()
返回false并中断了循环。