Search code examples
gofirebirdfirebird-3.0

Implementing unique connections for each goroutine using firebirdsql


I'm intending to populate multiple firebird databases from multiple goroutines concurrently and in order to do that my worker function has a map (dbConnections) that holds the connections to databases (maps the name of the database to the connection):

func worker() {
    dbConnections := map[string]*sql.DB {}
    for dbName, dbFileName := range dbFiles {
        connection, err := sql.Open("firebirdsql", ("sysdba:master@localhost:3050/" + url.PathEscape(dbsPath + dbFileName)))
        err = connection.Ping()
        if err != nil {
            fmt.Println("Ping failed: ", err.Error()
            return
        } else {
            dbConnections[dbName] = connection
            fmt.Println(fmt.Sprintf("Connected to the: %v", dbName))
            defer dbConnections[dbName].Close()
        }
    }

    // using the connections to populate databases...
    // ...
}

The problem is that when I run worker function as just 1 goroutine, everything works just fine, but as soon as I increase the number of goroutines, it seems that dbConnections from other goroutines gets messed up and sql executions complain about insertion into non existing tables!

How can I create dbConnections in such a way that every goroutine, has its own unique version of it?

Edit:


Solution

  • As many mentioned in the comment section, the problem was because of thread-safety in firebirdsql and especially when creating new tables. Defining a mutex and enclosing the sql execution method between mutex.Lock() and mutex.Unlock() (so that only one goroutine can create tables at any given time) solved the problem.