如果您的應用側使用Go語言,且數據庫連接創建頻繁(例如短連接場景)或連接數量較大(大于MySQL數據庫的連接數限制),您可以參考本教程通過Go驅動包Go-MySQL-Driver連接RDS MySQL數據庫,降低連接建立頻率以減少數據庫主線程的開銷。此外,本文還提供連接后操作RDS MySQL數據庫的方法。
Go-MySQL-Driver為Go語言的第三方數據庫驅動包,支持連接MySQL與MariaDB數據庫,詳細信息請參見Go-MySQL-Driver。
使用限制
RDS MySQL實例的數據庫版本僅支持5.7、8.0。
準備工作
使用Go-MySQL-Driver連接數據庫
1. 依賴引入
在Go項目的
go.mod
文件中,添加go-sql-driver
依賴:require ( github.com/go-sql-driver/mysql v1.8.1 )
在
.go
文件中導入數據庫驅動的依賴:import ( "github.com/go-sql-driver/mysql" )
2. 連接池初始化
在.go
文件的main方法中初始化連接池并配置以下參數,示例如下:
Addr // 創建一個數據庫連接
cfg := mysql.NewConfig()
cfg.User = "****" //您需手動替換為實際數據庫用戶名
cfg.Passwd = "****" //您需手動替換為實際數據庫密碼
cfg.Net = "tcp" //連接類型為TCP,保持默認,無需您手動修改
cfg.Addr = "rm-2zefwjx1s8156******.mysql.rds.aliyuncs.com:3306" //您需手動替換為實際MySQL數據庫連接地址和端口號
cfg.DBName = "****" //您需手動替換為實際數據庫名稱
conn, err := mysql.NewConnector(cfg)
if err != nil {
panic(err.Error())
}
db := sql.OpenDB(conn)
defer db.Close()
// 設置連接池參數
db.SetMaxOpenConns(20) // 設置連接池中最大打開的連接數, 您可根據實際需要手動調整
db.SetMaxIdleConns(2) // 設置連接池中最大空閑的連接數, 您可根據實際需要手動調整
db.SetConnMaxIdleTime(10 * time.Second) // 連接在連接池中的最長的空閑時間, 您可根據實際需要手動調整
db.SetConnMaxLifetime(80 * time.Second) // 設置連接的最大生命周期, 您可根據實際需要手動調整
RDS MySQL數據庫連接地址和端口的獲取方法,請參見查看和管理實例連接地址和端口。
附錄:連接池關鍵參數配置
推薦配置“推薦配置的參數”模塊,降低數據庫運行風險;您可以選擇性配置“可選擇配置的參數模塊”,用以提升使用性能。
為了最大程度地避免潛在的風險和不確定性,您在將新的參數值用于生產環境前,建議至少進行一輪完整的功能測試和性能測試,以確保系統穩定性和可靠性。
推薦配置的參數
參數名 | 含義 | 默認值 | 推薦值 | 說明 |
maxIdleTime | 設置最大空閑時間(單位:分鐘)。 | 0 | 10~30 |
|
maxLifetime | 設置連接的生命周期時間(單位:小時)。 | 0 | 1~8 |
|
maxOpen | 設置連接池中允許的最大連接數。 | 0 | 100 |
|
maxIdleCount | 設置連接池中允許的最大空閑連接數。 | 2 | 20 |
|
readTimeout | I/O讀取的超時時間,您可按需指定為毫秒(ms)、秒(s)或分鐘(m)。 | 0 | 10000ms-60000ms |
|
writeTimeout | I/O寫入的超時時間,您可按需指定為毫秒(ms)、秒(s)或分鐘(m)。 | 0 | 10000ms-60000ms |
|
可選擇配置的參數
參數名 | 含義 | 默認值 | 推薦值 | 說明 |
timeout | 連接建立的超時時間,您可按需指定為毫秒(ms)、秒(s)或分鐘(m)。 | 默認值是根據操作系統的默認值來設定。 | 3000ms |
|
操作數據庫
創建表
本文以創建一個名為 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
}
寫入數據
本文以在 userinfo
表中寫入數據為例演示。
方法一:直接寫入數據
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)
方法二:通過綁定參數的方式寫入數據
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)
更新數據
本文以更新userinfo
表中的數據為例演示。
stmt, err = db.Prepare("UPDATE userinfo SET username=?, departname=?, created=? WHERE uid=?")
if err != nil {
// 如果準備語句時出現錯誤,則進行錯誤處理
}
res, err = stmt.Exec("Robert", "Sales", "2024-09-23", 2)
if err != nil {
fmt.Println(err)
}
rowCnt, _ := res.RowsAffected()
fmt.Println(rowCnt)
查詢數據
本文以查詢 userinfo
表中username=Linda
的數據為例演示。
方法一:直接查詢數據
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)
}
方法二:通過綁定參數的方式執行參數化查詢
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)
}
刪除數據
本文以刪除userinfo
表中uid=1
的數據為例演示。
del_stmt, _ := db.Prepare("DELETE FROM userinfo WHERE uid=?")
del_stmt.Exec(1)
完整示例
package main
import (
"database/sql"
"fmt"
"github.com/go-sql-driver/mysql"
"time"
)
func main() {
//創建一個數據庫連接
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()
// 設置連接池參數
db.SetMaxOpenConns(20) // 設置連接池中最大打開的連接數
db.SetMaxIdleConns(2) // 設置連接池中最大空閑的連接數
db.SetConnMaxIdleTime(5 * time.Minute) // 設置連接在連接池中的最長的空閑時間
db.SetConnMaxLifetime(8 * time.Minute) // 設置連接的最大生命周期
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", "研發", "2016-06-17")
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
result, err := db.Exec("INSERT INTO userinfo (username, departname, created) VALUES (?, ?, ?)", "lily", "銷售", "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 {
// 處理錯誤
}
res, err = stmt.Exec("lisi", "測試", "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)
}
}
相關文檔
RDS MySQL數據庫代理中的連接池功能:設置RDS MySQL連接池