Skip to content

Commit

Permalink
MySQL driver: on connect try setting wsrep_sync_wait=4, swallow error…
Browse files Browse the repository at this point in the history
… 1193

In Galera clusters wsrep_sync_wait=4 ensures inserted rows to be synced over
all nodes before reporting success to their inserter. That allows inserting
child rows immediately after that on another node without running into
foreign key errors. MySQL single nodes will reject this with error 1193
"Unknown system variable" which is OK.
  • Loading branch information
Al2Klimov committed Nov 16, 2023
1 parent 85bde9e commit 87c520d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
14 changes: 11 additions & 3 deletions pkg/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ func (c RetryConnector) Connect(ctx context.Context) (driver.Conn, error) {
err := errors.Wrap(retry.WithBackoff(
ctx,
func(ctx context.Context) (err error) {
conn, err = c.Connector.Connect(ctx)
if conn, err = c.Connector.Connect(ctx); err == nil && c.driver.initConn != nil {
if err = c.driver.initConn(conn); err != nil {
_ = conn.Close()
conn = nil
}
}

return
},
shouldRetry,
Expand Down Expand Up @@ -67,7 +73,9 @@ func (c RetryConnector) Driver() driver.Driver {
// Driver wraps a driver.Driver that also must implement driver.DriverContext with logging capabilities and provides our RetryConnector.
type Driver struct {
ctxDriver
Logger *logging.Logger

Logger *logging.Logger
initConn func(driver.Conn) error
}

// OpenConnector implements the DriverContext interface.
Expand All @@ -85,7 +93,7 @@ func (d Driver) OpenConnector(name string) (driver.Connector, error) {

// Register makes our database Driver available under the name "icingadb-*sql".
func Register(logger *logging.Logger) {
sql.Register(MySQL, &Driver{ctxDriver: &mysql.MySQLDriver{}, Logger: logger})
sql.Register(MySQL, &Driver{ctxDriver: &mysql.MySQLDriver{}, Logger: logger, initConn: setGaleraOpts})
sql.Register(PostgreSQL, &Driver{ctxDriver: PgSQLDriver{}, Logger: logger})
_ = mysql.SetLogger(mysqlLogger(func(v ...interface{}) { logger.Debug(v...) }))
sqlx.BindDriver(PostgreSQL, sqlx.DOLLAR)
Expand Down
33 changes: 33 additions & 0 deletions pkg/driver/mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package driver

import (
"database/sql/driver"
"github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
)

// setGaleraOpts tries SET SESSION wsrep_sync_wait=4.
// Error 1193 "Unknown system variable" is ignored to support MySQL single nodes.
func setGaleraOpts(conn driver.Conn) error {
const galeraOpts = "SET SESSION wsrep_sync_wait=4"

stmt, err := conn.Prepare(galeraOpts)
if err != nil {
err = errors.Wrap(err, "can't prepare "+galeraOpts)
//lint:ignore SA1019 StmtExecContext isn't mandatory, would fall back anyway
} else if _, err = stmt.Exec(nil); err != nil {
err = errors.Wrap(err, "can't execute "+galeraOpts)
_ = stmt.Close()
} else if err = stmt.Close(); err != nil {
err = errors.Wrap(err, "can't close statement "+galeraOpts)
}

if err != nil {
var me *mysql.MySQLError
if errors.As(err, &me) && me.Number == 1193 {
err = nil
}
}

return err
}

0 comments on commit 87c520d

Please sign in to comment.