All Products
Search
Document Center

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

Last Updated:Nov 04, 2024

If your application uses the Go programming language and connections such as short-lived connections are frequently established between your application and an ApsaraDB RDS for MySQL instance or the maximum number of allowed connections to the RDS instance is reached, you can use Go-MySQL-Driver to connect to your RDS instance. This helps reduce the frequency at which your application connects to the RDS instance and lower the main thread overhead of the RDS instance. This topic describes how to use Go-MySQL-Driver to connect to an RDS instance. This topic also describes how to perform operations on databases on the RDS instance after the RDS instance is connected.

Note

Go-MySQL-Driver is a third-party database driver package in the Go programming language. You can use Go-MySQL-Driver to connect to MySQL and MariaDB databases. For more information, see Go-MySQL-Driver.

Limits

Only RDS instances that run MySQL 5.7 or 8.0 are supported.

Prerequisites

  • Go 1.20 or later is installed. For more information, see Download and install.

  • The IP address of your client is added to the IP address whitelist of the RDS instance. For more information, see Configure an IP address whitelist.

    Note

    If your application is deployed on an Elastic Compute Service (ECS) instance that resides in the same region and virtual private cloud (VPC) as the RDS instance, you do not need to configure an IP address whitelist.

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

1. Add a dependency

  1. Add the go-sql-driver dependency to the go.mod file of your Go project.

    require (
    	github.com/go-sql-driver/mysql v1.8.1
    )
  2. Import the dependency to the .go file.

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

2. Initialize the connection pool

Use the main method of the .go file to initialize the connection pool and configure related parameters. Sample code:

Addr // Create a database connection.
    cfg := mysql.NewConfig()
    cfg.User = "****" // Replace the value with the username of an account in your RDS instance.
    cfg.Passwd = "****" // Replace the value with the password of the account.
    cfg.Net = "tcp" // The connection type is TCP. Retain the default value. You do not need to modify the value.
    cfg.Addr = "rm-2zefwjx1s8156******.mysql.rds.aliyuncs.com:3306" // Replace the value with the endpoint and port number of your RDS instance.
    cfg.DBName = "****" // Replace the value with the name of the RDS instance.

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

    db := sql.OpenDB(conn)
    defer db.Close()

    // Configure the parameters related to the connection pool.
    db.SetMaxOpenConns(20)   // Specify the maximum number of open connections in the connection pool. You can modify the value based on your business requirements.
    db.SetMaxIdleConns(2)    // Specify the maximum number of idle connections in the connection pool. You can modify the value based on your business requirements.
    db.SetConnMaxIdleTime(10 * time.Second)   // Specify the maximum period of time that a connection in the connection pool can stay idle. You can modify the value based on your business requirements.
    db.SetConnMaxLifetime(80 * time.Second)   // Specify the maximum period of time that a connection can be reused. You can modify the value based on your business requirements.
Note

For more information about how to obtain the endpoint and port number of an RDS instance, see View and manage instance endpoints and ports.

Appendix:Key parameters of the connection pool

Important
  • We recommend that you configure the parameters in the Recommended configurations table to reduce database runtime risks. You can also configure the parameters in the Optional configurations table to improve database performance.

  • To minimize potential risks and uncertainties and ensure system stability and reliability, we recommend that you perform a complete feature and performance testing before you apply the new parameter values in your production environment.

Recommended configurations

Parameter

Description

Default value

Recommended value

Remarks

maxIdleTime

The maximum idle period of connections. Unit: minutes.

0

10 to 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

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

0

1 to 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

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

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 you set the parameter to a value less than or equal to 0, idle connections are closed.

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 to 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.

  • The value must be a number suffixed with a unit. For example, "30s" means 30 seconds and "0.5m" means 0.5 minutes.

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 to 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.

  • The value must be a number suffixed with a unit. For example, "30s" means 30 seconds and "0.5m" means 0.5 minutes.

Optional configurations

Parameter

Description

Default value

Recommended value

Remarks

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

  • The value must be a number suffixed with a unit. For example, "30s" means 30 seconds and "0.5m" means 0.5 minutes.

  • 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 a database

Create a table

In this example, a table named userinfo is created.

_, 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 the table

In this example, data is written to the userinfo table.

Method 1: Directly write data to a table

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

Method 2: Write data to a table by binding parameters

stmt, err := db.Prepare("INSERT INTO userinfo SET username=?,departname=?,created=?")
res, err := stmt.Exec("James", "Research", "2016-06-17")
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)

Update data

In this example, data in the userinfo table is updated.

stmt, err = db.Prepare("UPDATE userinfo SET username=?, departname=?, created=?  WHERE uid=?")
if err != nil {
    // Handle the errors that may occur when the system prepares SQL statements for execution.
}
res, err = stmt.Exec("Robert", "Sales", "2024-09-23", 2)
if err != nil {
    fmt.Println(err)
}
rowCnt, _ := res.RowsAffected()
fmt.Println(rowCnt)

Query data

In this example, a data record from the userinfo table in which the value of the username field is Linda is queried.

Method 1: Directly query data

rows, err := db.Query("SELECT username,departname,created FROM userinfo WHERE username=?", "Linda")
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)
}

Method 2: Query data by binding parameters

stmt, err = db.Prepare("SELECT username,departname,created FROM userinfo WHERE username=?")
if err != nil {
	fmt.Println("prepare error", err)
	return
}
rows, err = stmt.Query("Linda")
if err != nil {
	fmt.Println("query data error", err)
	return
}
defer rows.Close()
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)
}

Delete data

In this example, a data record from the userinfo table in which the value of the uid field is 1 is deleted.

del_stmt, _ := db.Prepare("DELETE FROM userinfo WHERE uid=?")
del_stmt.Exec(1)

Sample code

package main

import (
    "database/sql"
    "fmt"
    "github.com/go-sql-driver/mysql"
    "time"
)

func main() {
    // Create a database connection.
    cfg := mysql.NewConfig()
    cfg.User = "****"
    cfg.Passwd = "****"
    cfg.Net = "tcp"
    cfg.Addr = "rm-2zefwjx1s8156******.mysql.rds.aliyuncs.com:3306"
    cfg.DBName = "****"

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

    db := sql.OpenDB(conn)
    defer db.Close()

    // Configure the parameters related to the connection pool.
    db.SetMaxOpenConns(20)                 // Specify the maximum number of open connections in the connection pool.
    db.SetMaxIdleConns(2)                  // Specify the maximum number of idle connections in the connection pool.
    db.SetConnMaxIdleTime(5 * time.Minute) // Specify the maximum period of time that a connection in the connection pool can stay idle.
    db.SetConnMaxLifetime(8 * time.Minute) // Specify the maximum period of time that a connection can be reused.
    checkErr(err)

    _, 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
    }

    stmt, err := db.Prepare("INSERT userinfo SET username=?,departname=?,created=?")
    res, err := stmt.Exec("zhja", "R&D", "2016-06-17")
    id, err := res.LastInsertId()
    checkErr(err)
    fmt.Println(id)

    result, err := db.Exec("INSERT INTO userinfo (username, departname, created) VALUES (?, ?, ?)", "lily", "Sales", "2016-06-21")
    checkErr(err)
    ids, err := result.LastInsertId()
    fmt.Println(ids)

    del_stmt, _ := db.Prepare("DELETE FROM userinfo WHERE uid=?")
    del_stmt.Exec(1)

    stmt, err = db.Prepare("UPDATE userinfo SET username=?, departname=?, created=?  WHERE uid=?")
    if err != nil {
       // Handle errors.
    }
    res, err = stmt.Exec("lisi", "Test", "2024-09-23", 2)
    if err != nil {
       fmt.Println(err)
    }
    rowCnt, _ := res.RowsAffected()
    fmt.Println(rowCnt)

    rows, err := db.Query("SELECT username,departname,created FROM userinfo WHERE username=?", "lisi")
    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)
    }

    stmt, err = db.Prepare("SELECT username,departname,created FROM userinfo WHERE username=?")
    if err != nil {
       fmt.Println("prepare error", err)
       return
    }
    rows, err = stmt.Query("lisi")
    if err != nil {
       fmt.Println("query data error", err)
       return
    }
    defer rows.Close()
    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)
    }

}

func checkErr(err error) {
    if err != nil {
       panic(err)
    }
}

References