Retry aborted transactions on Spanner. (#103289)
* Retry aborted transactions on Spanner.
This commit is contained in:
@@ -2,11 +2,9 @@ package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/mattn/go-sqlite3"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
@@ -63,16 +61,17 @@ func (ss *SQLStore) inTransactionWithRetryCtx(ctx context.Context, engine *xorm.
|
||||
return err
|
||||
}
|
||||
|
||||
// special handling of database locked errors for sqlite, then we can retry 5 times
|
||||
var sqlError sqlite3.Error
|
||||
if errors.As(err, &sqlError) && retry < ss.dbCfg.TransactionRetries && (sqlError.Code == sqlite3.ErrLocked || sqlError.Code == sqlite3.ErrBusy) {
|
||||
if rollErr := sess.Rollback(); rollErr != nil {
|
||||
return fmt.Errorf("rolling back transaction due to error failed: %s: %w", rollErr, err)
|
||||
}
|
||||
// special handling of database locked errors for sqlite and spanner, then we can retry 5 times
|
||||
if r, ok := engine.Dialect().(xorm.DialectWithRetryableErrors); ok {
|
||||
if retry < ss.dbCfg.TransactionRetries && r.RetryOnError(err) {
|
||||
if rollErr := sess.Rollback(); rollErr != nil {
|
||||
return fmt.Errorf("rolling back transaction due to error failed: %s: %w", rollErr, err)
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * time.Duration(10))
|
||||
ctxLogger.Info("Database locked, sleeping then retrying", "error", err, "retry", retry, "code", sqlError.Code)
|
||||
return ss.inTransactionWithRetryCtx(ctx, engine, bus, callback, retry+1)
|
||||
time.Sleep(time.Millisecond * time.Duration(10))
|
||||
ctxLogger.Info("Database locked, sleeping then retrying", "error", err, "retry", retry)
|
||||
return ss.inTransactionWithRetryCtx(ctx, engine, bus, callback, retry+1)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user