All Products
Search
Document Center

ApsaraDB RDS:Use Go-MySQL-Driver to connect to an RDS instance

Last Updated:Feb 18, 2025

If your Go-based application frequently establishes short-lived connections with an ApsaraDB RDS for MySQL instance, or if you're reaching the maximum number of allowed connections, Go-MySQL-Driver can help. By using this driver, you can reduce connection frequency and lower the main thread overhead on the RDS instance. This topic also covers how to perform database operations once connected to the RDS instance.

Note

Go-MySQL-Driver is a third-party database driver package for Go. It supports connections to MySQL and MariaDB databases. For more information, see Go-MySQL-Driver.

Limits

Only RDS instances running MySQL 5.7 or 8.0 are supported.

Preparations

  • Download and install the Go environment. We recommend version 1.20 or later.

  • Add your client's IP address to the RDS instance's whitelist. For more information, see Configure a whitelist.

    Note

    If your application is deployed on an ECS instance in the same region and VPC as the RDS instance, you do not need to configure a whitelist.

Use Go-MySQL-Driver to connect to an RDS instance

1. Dependency introduction

  1. Include the go-sql-driver dependency in your Go project's go.mod file:

    require (
        github.com/go-sql-driver/mysql v1.8.1
    )
  2. Import the necessary packages in your file:

    import (
        // Import the database/sql package of the Go programming language. This package provides a general SQL interface.
        "database/sql"
        // Import the fmt package. This package is used for formatting input and output in the standard library of the Go programming language.
        "fmt"
        // This driver can be used to connect to and operate MySQL databases in the Go programming language.
        "github.com/go-sql-driver/mysql"
        // Import the time package of the Go programming language. This package is used to handle time-related operations.
        "time"
    )

2. Initialize the connection pool

Initialize the connection pool and set the following parameters in the main method of your file. Below is an example:

// Create a database connection
cfg := mysql.NewConfig()
cfg.User = "****"       // You need to manually replace this with the actual database username.
cfg.Passwd = "****"     // You need to manually replace this with the actual database password.
cfg.Net = "tcp"         // The connection type is TCP. You do not need to manually modify this.
cfg.Addr = "rm-2zefwjx1s8156******.mysql.rds.aliyuncs.com:3306" // You need to manually replace this with the actual MySQL database connection address and port number.
cfg.DBName = "****"     // You need to manually replace this with the actual database name.

conn, err := mysql.NewConnector(cfg)
if err != nil {
    panic(err.Error())
}

db := sql.OpenDB(conn)
defer func(db *sql.DB) {
    err := db.Close()
    if err != nil {
        fmt.Printf("Error closing database connection: %v\n", err)
    }
}(db)
// Configure the parameters related to the connection pool.
db.SetMaxOpenConns(20)                 // Configure the maximum number of open connections in the connection pool. You can manually adjust this based on your actual needs.
db.SetMaxIdleConns(2)                  // Configure the maximum number of idle connections in the connection pool. You can manually adjust this based on your actual needs.
db.SetConnMaxIdleTime(10 * time.Second) // Configure the maximum idle period of connections in the connection pool. You can manually adjust this based on your actual needs.
db.SetConnMaxLifetime(80 * time.Second) // Configure the maximum period of time that a connection can be reused. You can manually adjust this based on your actual needs.
Note

To obtain the connection address and port for an RDS MySQL database, see View and Manage Instance Connection Addresses and Ports.

Appendix: Key parameter configurations of the connection pool

Important
  • Recommended configurations are provided to minimize operational risks. You can optionally configure additional parameters to enhance performance.

  • To ensure system stability and reliability, complete feature and performance testing is recommended before applying new parameter values in a production environment.

Recommended configurations

Parameter name

Meaning

Default value

Recommended value

Description

maxIdleTime

Configure the maximum idle period of connections. Unit: minutes.

0

10~30

  • The default value 0 specifies that connections do not time out.

  • We recommend that you configure this parameter for your application based on actual requirements. You can use the SetConnMaxIdleTime method to configure the parameter.

maxLifetime

Configure the maximum period of time that a connection can be reused. Unit: hours.

0

1~8

  • The default value 0 specifies that connections are always available for reuse and no limits are imposed.

  • This parameter is used to prevent long-lived connections and save resources. You can use the SetConnMaxLifetime method to configure the parameter.

maxOpen

Configure the maximum number of connections in the connection pool.

0

100

  • The default value 0 specifies that no limits are imposed.

  • If the value of the MaxIdleConns parameter is greater than 0 and is greater than the new value of the MaxOpenConns parameter, the value of the MaxIdleConns parameter is decreased to meet the limit of the MaxOpenConns parameter.

  • We recommend that you configure this parameter for your application based on actual requirements. You can use the SetMaxOpenConns method to configure the parameter.

maxIdleCount

Configure the maximum number of idle connections in the connection pool.

2

20

  • You can configure this parameter to reserve a specific number of connections to quickly respond to database request bursts.

  • If the value of the MaxOpenConns parameter is greater than 0 and less than the new value of the MaxIdleConns parameter, the new value of the MaxIdleConns is decreased to meet the limit of the MaxOpenConns parameter.

  • You can use the SetMaxIdleConns method to configure the parameter.

  • If the parameter n <= 0 is set, idle connections are not reserved.

readTimeout

The timeout period for I/O reads. You can specify the value in milliseconds (ms), seconds (s), or minutes (m) based on your business requirements.

0

10000ms-60000ms

  • The default value 0 specifies that no timeout limits are imposed. We recommend that you retain the default value. You can modify the value based on your business requirements.

  • Use the time.Duration type in the Go standard library to directly assign a value. Use predefined unit constants to configure the parameter, such as cfg.readTimeout = 30*time.Second. Avoid using string formats, such as 30s.

writeTimeout

The timeout period for I/O writes. You can specify the value in milliseconds (ms), seconds (s), or minutes (m) based on your business requirements.

0

10000ms-60000ms

  • The default value 0 specifies that no timeout limits are imposed. We recommend that you retain the default value. You can modify the value based on your business requirements.

  • Use the time.Duration type in the Go standard library to directly assign a value. Use predefined unit constants to configure the parameter, such as cfg.writeTimeout=30*time.Second. Avoid using string formats, such as 30s.

Optional configurations

Parameter name

Meaning

Default value

Recommended value

Description

timeout

The timeout period for establishing a connection. You can specify the value in milliseconds (ms), seconds (s), or minutes (m) based on your business requirements.

The default value varies based on the default value of the operating system.

3000ms

  • Use the time.Duration type in the Go standard library to directly assign a value. Use predefined unit constants to configure the parameter, such as cfg.timeout=30*time.Second. Avoid using string formats, such as 30s.

  • We recommend that you specify a timeout period in the range of 1s to 10s when you configure a connection pool. The timeout period varies based on the network quality and the distance between the application and the server.

Perform operations on databases

Create a table

Below is an example of how to create a table named .

_, err = db.Exec("create table  if not exists userinfo( uid int auto_increment, username varchar(20) not null default '', departname varchar(20) not null default '', created varchar(10) not null default '', primary key(uid) );")
if err != nil {
    fmt.Println("create table error ", err)
    return
}

Write data to a table

Below is an example of how to write data to the userinfo table.

Method 1: Directly write data to a table

stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
res, err := stmt.Exec("James", "Research", "2016-06-17")
id, err := res.LastInsertId()
if err != nil {
    panic(err)
}
fmt.Println(id)

Method 2: Write data to a table by binding parameters

result, err := db.Exec("INSERT INTO userinfo (username, departname, created) VALUES (?, ?, ?)", "Linda", "Testing", "2016-06-21")
if err != nil {
    panic(err)
}
ids, err := result.LastInsertId()
fmt.Println(ids)

Update data in a table

Below is an example of how to update data in the table.

stmtUpdate, err := db.Prepare("UPDATE userinfo SET username=?, departname=?, created=? WHERE username=?")
if err != nil {
    fmt.Println("Prepare update statement error:", err)
    return
}
resUpdate, err := stmtUpdate.Exec("Robert", "Sales", "2024-09-23", "Linda")
if err != nil {
    fmt.Println(err)
}
rowCnt, _ := resUpdate.RowsAffected()
fmt.Println(rowCnt)

Query data from a table

Below is an example of how to query data from the userinfo table where username=Robert.

Method 1: Directly query data

rows, err := db.Query("SELECT username,departname,created FROM userinfo WHERE username=?", "Robert")
if err != nil {
    panic(err)
}
for rows.Next() {
 var username, departname, created string
 if err := rows.Scan(&username, &departname, &created); err != nil {
     fmt.Println(err)
 }
 fmt.Println("username:", username, "departname:", departname, " created:", created)
}
defer func(rows *sql.Rows) {
 err := rows.Close()
 if err != nil {
     fmt.Println(err)
 }
}(rows)

Method 2: Query data by binding parameters

stmtQuery, err := db.Prepare("SELECT username,departname,created FROM userinfo WHERE username=?")
if err != nil {
    fmt.Println("prepare error", err)
    return
}
rowData, err := stmtQuery.Query("Robert")
if err != nil {
    fmt.Println("query data error", err)
    return
}
for rowData.Next() {
 var username, departname, created string
 if err := rowData.Scan(&username, &departname, &created); err != nil {
     fmt.Println(err)
 }
 fmt.Println("username:", username, "departname:", departname, "created:", created)
}
defer func(rows *sql.Rows) {
 err := rows.Close()
 if err != nil {
     fmt.Println(err)
 }
}(rowData)

Delete data from a table

Below is an example of how to delete data from the userinfo table where .

delStmt, _ := db.Prepare("DELETE FROM userinfo WHERE username=?")
resultDel, err := delStmt.Exec("James")
if err != nil {
    panic(err)
}
rowAffect, _ := resultDel.RowsAffected()
fmt.Println("Data deletion completed.", rowAffect)

Complete example

package main

import (
    // Import the database/sql package of the Go programming language. This package provides a general SQL interface.
    "database/sql"
    // Import the fmt package. This package is used for formatting input and output in the standard library of the Go programming language.
    "fmt"
    // This driver can be used to connect to and operate MySQL databases in the Go programming language.
    "github.com/go-sql-driver/mysql"
    // Import the time package of the Go programming language. This package is used to handle time-related operations.
    "time"
)

func main() {
    // Create a database connection
    cfg := mysql.NewConfig()
    cfg.User = "****"                                                   /* Username */
    cfg.Passwd = "****"                                                 /* Password */
    cfg.Net = "tcp"                                                     /* Connection type */
    cfg.Addr = "rm-2ze1vw17v542q6b****.mysql.pre.rds.aliyuncs.com:3306" /* Connection address */
    cfg.DBName = "****"                                                 /* Database name */
    cfg.Timeout = 3 * time.Second                                       /* The timeout period for establishing a connection to the database. You can specify the value in milliseconds (ms), seconds (s), or minutes (m) based on your business requirements. */
    cfg.ReadTimeout = 60 * time.Second                                  /* The timeout period for I/O reads. You can specify the value in milliseconds (ms), seconds (s), or minutes (m) based on your business requirements. */
    cfg.WriteTimeout = 60 * time.Second                                 /* The timeout period for I/O writes. You can specify the value in milliseconds (ms), seconds (s), or minutes (m) based on your business requirements. */

    conn, err := mysql.NewConnector(cfg)
    if err != nil {
        panic(err.Error())
    }

    db := sql.OpenDB(conn)
    defer func(db *sql.DB) {
        err := db.Close()
        if err != nil {
            fmt.Printf("Error closing database connection: %v\n", err)
        }
    }(db)

    // Configure parameters related to the connection pool.
    db.SetMaxOpenConns(100)                 /* Configure the maximum number of open connections in the connection pool. */
    db.SetMaxIdleConns(20)                  /* Configure the maximum number of idle connections in the connection pool. */
    db.SetConnMaxIdleTime(10 * time.Minute) /* Configure the maximum idle period of connections in the connection pool. */
    db.SetConnMaxLifetime(8 * time.Hour)    /* Configure the maximum period of time that a connection can be reused. */

    // Create a table named userinfo
    _, err = db.Exec("create table  if not exists userinfo( uid int auto_increment, username varchar(20) not null default '', departname varchar(20) not null default '', created varchar(10) not null default '', primary key(uid) );")
    if err != nil {
        fmt.Println("create table error ", err)
        return
    }

    // Directly write data to a table
    stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
    res, err := stmt.Exec("James", "Research", "2016-06-17")
    id, err := res.LastInsertId()
    if err != nil {
        panic(err)
    }
    fmt.Println(id)

    // Write data to a table by binding parameters
    result, err := db.Exec("INSERT INTO userinfo (username, departname, created) VALUES (?, ?, ?)", "Linda", "Testing", "2016-06-21")
    if err != nil {
        panic(err)
    }
    ids, err := result.LastInsertId()
    fmt.Println(ids)

    // Update data in a table
    stmtUpdate, err := db.Prepare("UPDATE userinfo SET username=?, departname=?, created=? WHERE username=?")
    if err != nil {
        fmt.Println("Prepare update statement error:", err)
        return
    }
    resUpdate, err := stmtUpdate.Exec("Robert", "Sales", "2024-09-23", "Linda")
    if err != nil {
        fmt.Println(err)
    }
    rowCnt, _ := resUpdate.RowsAffected()
    fmt.Println(rowCnt)

    // Directly query data
    rows, err := db.Query("SELECT username,departname,created FROM userinfo WHERE username=?", "Robert")
    if err != nil {
        panic(err)
    }
    for rows.Next() {
        var username, departname, created string
        if err := rows.Scan(&username, &departname, &created); err != nil {
            fmt.Println(err)
        }
        fmt.Println("username:", username, "departname:", departname, "created:", created)
    }
    defer func(rows *sql.Rows) {
        err := rows.Close()
        if err != nil {
            fmt.Println(err)
        }
    }(rows)

    // Query data by binding parameters
    stmtQuery, err := db.Prepare("SELECT username,departname,created FROM userinfo WHERE username=?")
    if err != nil {
        fmt.Println("prepare error", err)
        return
    }
    rowData, err := stmtQuery.Query("Robert")
    if err != nil {
        fmt.Println("query data error", err)
        return
    }
    for rowData.Next() {
        var username, departname, created string
        if err := rowData.Scan(&username, &departname, &created); err != nil {
            fmt.Println(err)
        }
        fmt.Println("username:", username, "departname:", departname, "created:", created)
    }
    defer func(rows *sql.Rows) {
        err := rows.Close()
        if err != nil {
            fmt.Println(err)
        }
    }(rowData)

    // Delete data from a table
    delStmt, _ := db.Prepare("DELETE FROM userinfo WHERE username=?")
    resultDel, err := delStmt.Exec("James")
    if err != nil {
        panic(err)
    }
    rowAffect, _ := resultDel.RowsAffected()
    fmt.Println("Data deletion completed.", rowAffect)
}

References