一 问题描述
Lock wait timeout exceeded; try restarting transaction
二 处理过程
首先假如在生产中遇到这个问题,我们必然是先找到这个循环等待的线程,给他kill了,如下
然后kill掉957和958
三 系统调节
一般mysql的inodb有个默认事物等待时间,超过这个时间他会自动结束且抛出异常,参数为innodb_lock_wait_timeout,默认50s,修改它即可
四 代码链路追踪
分析出代码是在同一个表的同一行进行第二次updt操作的时候锁住了,然后也查阅相关资料,发现有的coder说这种情况会发生锁死。然后本人做了个测试
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"time"
)
var MysqlDb *sql.DB
var MysqlDbErr error
// 初始化链接
//func InitDb() {
func init() {
m_user := "wbw"
m_pd := "123456"
m_host := "127.0.0.1"
m_pt := "3306"
m_db := "test_local"
dbDSN := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s", m_user, m_pd, m_host, m_pt, m_db, "utf8")
// 打开连接失败
MysqlDb, MysqlDbErr = sql.Open("mysql", dbDSN)
//defer MysqlDb.Close();
if MysqlDbErr != nil {
panic("数据源配置不正确: " + MysqlDbErr.Error())
}
// 最大连接数
MysqlDb.SetMaxOpenConns(100)
// 闲置连接数
MysqlDb.SetMaxIdleConns(20)
// 最大连接周期
MysqlDb.SetConnMaxLifetime((30)*time.Second)
if MysqlDbErr = MysqlDb.Ping(); nil != MysqlDbErr {
panic("数据库链接失败: " + MysqlDbErr.Error())
}
}
func main(){
//ifupdt,err := UpdtCarrierRemark("asd","hah2")
ifupdt,err := UpdtCarrierRemarkTrx("asd","hatt")
fmt.Println(ifupdt,err)
}
func UpdtCarrierRemark(asn_id string,remark string) (bool,error){
_,errs := MysqlDb.Exec("update ls_wms_asn set " +
"remark=? where (asn_id=?) ",remark,asn_id)
if errs != nil{
fmt.Println(errs)
return false,errs
}
return true,nil
}
func UpdtCarrierRemarkTrx(asn_id string,remark string) (bool,error){
tx, _ := MysqlDb.Begin()
_,errs := tx.Exec("update ls_wms_asn set " +
"remark=? where (asn_id=?) ",remark,asn_id)
if errs != nil{
fmt.Println(errs)
tx.Rollback()
return false,errs
}
_,errs2 := tx.Exec("update ls_wms_asn set " +
"remark_ct=201 where (asn_id=?) ",asn_id)
if errs2 != nil{
fmt.Println(errs2)
tx.Rollback()
return false,errs2
}
tx.Commit()
return true,nil
}
做了验证后发现并没有发生锁死的情况,然后猜测可能是并发不够,所以专门又用ab测试了1s钟100次的并发,也未发生锁死。
所以暂时排除此种原因
五 小失误导致
原来我代码中用的是MysqlDb.Exec,而非tx.Exec
当我们开启事务tx, _ := MysqlDb.Begin()后,对db的操作都应该用tx来完成,而非常规的DB单例变量。
虽然原因找到了,是个简单失误,但是能够简单回顾下事物锁死的处理过程,也算小有收获