From f697f81950d50d78ac9adbc7b6bb00a327da82cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 15 May 2017 12:19:19 +0200 Subject: [PATCH] sqlite: fixed database table looked handling, now retries up to 5 times, fixes #7992 --- pkg/services/sqlstore/shared.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkg/services/sqlstore/shared.go b/pkg/services/sqlstore/shared.go index be4266477c7..72566a93583 100644 --- a/pkg/services/sqlstore/shared.go +++ b/pkg/services/sqlstore/shared.go @@ -1,9 +1,12 @@ package sqlstore import ( + "time" + "github.com/go-xorm/xorm" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" + sqlite3 "github.com/mattn/go-sqlite3" ) type dbTransactionFunc func(sess *xorm.Session) error @@ -19,6 +22,10 @@ func (sess *session) publishAfterCommit(msg interface{}) { } func inTransaction(callback dbTransactionFunc) error { + return inTransactionWithRetry(callback, 0) +} + +func inTransactionWithRetry(callback dbTransactionFunc, retry int) error { var err error sess := x.NewSession() @@ -30,6 +37,16 @@ func inTransaction(callback dbTransactionFunc) error { err = callback(sess) + // special handling of database locked errors for sqlite, then we can retry 3 times + if sqlError, ok := err.(sqlite3.Error); ok && retry < 5 { + if sqlError.Code == sqlite3.ErrLocked { + sess.Rollback() + time.Sleep(time.Millisecond * time.Duration(10)) + sqlog.Info("Database table locked, sleeping then retrying", "retry", retry) + return inTransactionWithRetry(callback, retry+1) + } + } + if err != nil { sess.Rollback() return err