Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connection pooling with SQL driver in Go

Tags:

sql

go

What is the best practice for storing a connection to a database in Go language?

In Java for example you can use singletons, some IoC containers like Spring. What is the best practice in it's lifecycle? How to release it after application close?

like image 948
Andre Minov Avatar asked Nov 30 '15 09:11

Andre Minov


People also ask

What is connection pooling in Golang?

Connection pooling means that executing two consecutive statements on a single database might open two connections and execute them separately. It is fairly common for programmers to be confused as to why their code misbehaves.

What is SQL connection pooling?

It manages connections by keeping alive a set of active connections for each given connection configuration. Whenever a user calls Open on a connection, the pooler looks for an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection.

How do I enable connection pooling in ODBC application?

You can use the Connection Pooling tab of the ODBC Data Source Administrator dialog box to enable and disable performance monitoring. Double-click a driver name to set the connection time-out period. At the driver level, connection pooling is enabled by the CPTimeout registry value.


1 Answers

There is nothing wrong about using a Singleton pattern here too.

I would use something like this:

var db *sql.DB = nil

func GetDB() (*sql.DB, error) {
    if db == nil {
        conn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=require",
            DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
        log.Println("Creating a new connection: %v", conn)

        d, err := sql.Open("postgres", conn)
        if err != nil {
            return nil, err
        }
        db = d
    }

    return db, nil
}

With this exported function you can receive a connection from all other packages.

Update of the answer according to the comments (thanks @all for the information)!:

The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections. Thus, the Open function should be called just once. It is rarely necessary to close a DB.¹

It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.²

I would say that there is no forcing reason to call close on the database connection. I found no other statements. Despite this I would use a defer GetDB().close() in the main function - just for the completeness of the code.

Another thing I would like to note is that the connection should be verified by a db.Ping() otherwise the connection could be established but the database may not exist.

With this new information I wouldn't bother using some mutexes to ensure that the database is established. I would create a new DBInit() and run it inside the init() function of the main package.

like image 176
Mark Avatar answered Sep 20 '22 11:09

Mark