【发布时间】:2018-07-12 20:43:21
【问题描述】:
在我的小型 Web 服务中,尝试在日志表中插入新行时出现死锁 - 错误 1213:尝试获取锁时发现死锁;尝试重新启动事务。
当我多次执行方法 Test 时,我得到了错误。如何避免死锁?
func main() {
var err error
db, err = sql.Open("mysql", dbUser+":"+dbPassword+"@tcp("+dbAddr+")/"+dbDatabase)
if err != nil {
panic(err.Error())
}
defer db.Close()
err = db.Ping()
if err != nil {
panic(err.Error())
}
defer db.Close()
router := mux.NewRouter()
router.HandleFunc("/test/", Test).Methods("POST")
log.Error(http.ListenAndServe(":8080", router))
}
func Test(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Write(body)
_ = insertLog("Test")
}
func insertLog(msg string) error {
var sqlString string
sqlString = "insert into logs (date_time, msg) values(now(),?)"
stmt, err := db.Prepare(sqlString)
if err != nil {
log.Error(err)
return err
}
defer stmt.Close()
_, err = stmt.Exec(msg)
if err != nil {
log.Error("Msg: %s, Func: %s", err, function)
return err
}
defer stmt.Close()
return err
}
架构(来自评论):
CREATE TABLE IF NOT EXISTS logs (
date_time datetime NOT NULL,
msg varchar(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
【问题讨论】:
-
对于初学者,您在 defer 中关闭了两次语句。
-
它与死锁有什么关系?
-
我没有检查它内部的作用,只是指出来。您可能希望发布您的架构以及有关您如何运行测试的更多详细信息。
-
但是这段代码是有效的。数据库是 10.0.21-MariaDB-wsrep - MariaDB 服务器。 go version go1.8 linux/amd64 mysql driver is github.com/go-sql-driver/mysql Table logs CREATE TABLE IF NOT EXISTS logs ( date_time datetime NOT NULL, msg varchar(100) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET= latin1;代码
-
你不能只用一个资源死锁......你确定这个插入是唯一运行的东西吗?你能打印错误的东西并确认你确实在该代码中遇到了死锁吗?