Go 在 Linux 下的数据库操作优化要点
一 连接池与资源管理
import (
"database/sql"
"time"
_ "github.com/go-sql-driver/mysql"
)
func initDB() *sql.DB {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := sql.Open("mysql", dsn)
if err != nil { panic(err) }
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(30 * time.Minute)
if err = db.Ping(); err != nil { panic(err) }
return db
}
以上做法可减少连接建立/销毁开销、提升吞吐并保障连接“新鲜度”。二 SQL 与索引优化
// 预编译
stmt, _ := db.Prepare("SELECT id, name FROM users WHERE status = ? AND id > ? ORDER BY id ASC LIMIT ?")
defer stmt.Close()
var lastID int64 = 0
for {
rows, _ := stmt.QueryContext(ctx, "active", lastID, 100)
defer rows.Close()
hasMore := false
for rows.Next() {
var id int64
var name string
rows.Scan(&id, &name)
// 业务处理
lastID = id
hasMore = true
}
if !hasMore { break }
}
通过预编译、覆盖索引与游标分页的组合,可显著降低查询延迟与资源占用。三 批量写入与事务控制
tx, _ := db.Begin()
defer func() {
if p := recover(); p != nil { tx.Rollback(); panic(p) }
}()
stmt, _ := tx.Prepare("INSERT INTO logs(message) VALUES(?)")
defer stmt.Close()
for _, msg := range messages {
if _, err := stmt.Exec(msg); err != nil {
tx.Rollback()
return err
}
}
tx.Commit()
批量 + 事务能显著减少网络往返与日志刷盘次数,提高写入吞吐与一致性。四 上下文超时与错误处理
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
var name string
err := db.QueryRowContext(ctx, "SELECT name FROM users WHERE id = ?", 1).Scan(&name)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
// 正常“未找到”
} else {
// 网络/超时/其他错误处理
}
}
超时与精细化错误处理能提升稳定性与可观测性,避免雪崩与资源泄漏。五 Linux 运行时与监控建议