全部產品
Search
文件中心

Lindorm:基於Go的應用開發

更新時間:Jul 25, 2025

本文介紹使用Go語言的database/sql包和SQL語句在Lindorm寬表應用中進行開發的方法和樣本。

前提條件

  • 已安裝GO環境,建議安裝Go 1.17及以上版本。如何安裝,請參見Go

  • 已開通MySQL協議相容功能。如何開通,請參見開通MySQL協議相容功能

  • 已將用戶端IP添加至白名單,具體操作請參見設定白名單

注意事項

  • Lindorm SQL前端接入節點使用SLB(負載平衡)將用戶端請求分發至各個前端節點。為確保用戶端請求能夠更均勻地分配到所有前端節點,

    設定的串連保持時間建議不宜過長,您可通過配置SetConnMaxLifetime參數來實現串連的定期重新整理。

  • 複雜網路情況下,當遇到網關效能達到瓶頸、網路鏈路長、網路抖動、重傳率或丟包率高等情形,可能會導致串連中斷。建議確保串連池配置合理,並在必要時通過業務代碼側的重試機制最佳化。

  • 服務端升級重啟時,串連可能會短暫中斷。即使使用了串連池,業務側仍可能感知到異常。建議捕獲異常並重試。

  • 根據業務情況合理調整串連池配置,並確保該配置生效。請確保串連池的串連數量滿足業務需求,避免因串連不足而導致業務等待串連,從而引起回應時間(RT)上升。您可以通過列印串連池狀態(fmt.Printf("%+v\n", db.Stats()))來診斷問題。

操作步驟

  1. 在Go專案的go.mod檔案中,添加Golang MySQL Driver依賴。

    require github.com/go-sql-driver/mysql v1.7.1
  2. 配置串連參數。

    const ( 
        user = "user"
        password = "test"
        host = "ld-uf6k8yqb741t3****-proxy-sql-lindorm.lindorm.rds.aliyuncs.com"
        port = 33060
        database = "default"
        connectTimeout = "10s"
    )

    參數說明

    參數

    說明

    user

    如果您忘記使用者密碼,可以通過Lindorm寬表引擎的叢集管理系統修改密碼。具體操作,請參見修改使用者密碼

    password

    host

    Lindorm寬表引擎的MySQL相容地址。如何擷取,請參見查看串連地址

    重要
    • 如果應用部署在ECS執行個體,建議您通過專用網路訪問Lindorm執行個體,可獲得更高的安全性和更低的網路延遲。

    • 如果應用部署在本地,在通過公網串連Lindorm執行個體前,需在控制台開通公網地址。開通方式:在控制台選擇資料庫連接 > 寬表引擎,在寬表引擎頁簽單擊開通公網地址

    • 通過專用網路訪問Lindorm執行個體,host請填寫MySQL相容地址對應的專用網路地址。通過公網訪問Lindorm執行個體,host請填寫MySQL相容地址對應的公網地址。

    port

    Lindorm寬表引擎MySQL協議的連接埠,固定為33060。

    database

    需要串連的資料庫名稱。預設串連default資料庫。

    connectTimeout

    資料庫連接的逾時時間。單位為秒(s)。

  3. 建立串連,通過寬表SQL文法使用Lindorm寬表引擎。以查詢所有資料庫為例。

    url := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?timeout=%s", user, password, host, port, database, connectTimeout)
    db, err := sql.Open("mysql", url)
    if err != nil {
    	panic(err.Error())
    }
    //設定可開啟串連數的最大值,預設值為0,表示不限制。根據業務實際情況設定,避免串連不夠用,等待串連。
    db.SetMaxOpenConns(20)
    //設定最大閑置串連數, 預設值為2。建議SetMaxIdleConns設定為和SetMaxOpenConns相等。
    db.SetMaxIdleConns(20)
    // 設定串連的最大空閑時間,預設值為0,表示不逾時。建議設定為 8 分鐘。
    db.SetConnMaxIdleTime(8 * time.Minute)
    // 設定串連的最大使用時間,避免長時間使用長串連,造成串連不均衡。建議設定為 30 分鐘。
    db.SetConnMaxLifetime(30 * time.Minute)
    
    defer db.Close()
    
    // 擷取資料庫中所有的database
    {
    	rows, err := db.Query("show databases")
    	if err != nil {
    		panic(err.Error())
    	}
        defer rows.Close()
    	for rows.Next() {
    		var dbName string
    		err := rows.Scan(&dbName)
    		if err != nil {
    			panic(err.Error())
    		}
    		fmt.Println(dbName)
    	}
    }

完整樣本

完整範例程式碼如下:

package main
import (
    "database/sql"
    "fmt"
    "time"
    _ "github.com/go-sql-driver/mysql"
)
const (
    //user為Lindorm寬表引擎的使用者名稱
    user = "user"
    //password為Lindorm寬表引擎的密碼
    password = "test"
    //host為Lindorm寬表引擎的MySQL相容地址
    host = "ld-uf6k8yqb741t3****-proxy-sql-lindorm-public.lindorm.rds.aliyuncs.com"
    //Lindorm寬表引擎MySQL協議的連接埠,固定為33060
    port = 33060
    //database為需要串連的資料庫名稱
    database = "default"
    //資料庫連接的逾時時間
    connectTimeout = "20s"
)
func main() {
	//開啟資料庫連接
	url := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?timeout=%s", user, password, host, port, database, connectTimeout)
	db, err := sql.Open("mysql", url)
	if err != nil {
		panic(err.Error())
	}
    
    //設定可開啟串連數的最大值,預設值為0,表示不限制。根據業務實際情況設定,避免串連不夠用,等待串連。
    db.SetMaxOpenConns(20)
    //設定最大閑置串連數, 預設值為2。建議SetMaxIdleConns設定為和SetMaxOpenConns相等。
    db.SetMaxIdleConns(20)
    // 設定串連的最大空閑時間,預設值為0,表示不逾時。建議設定為 8 分鐘。
    db.SetConnMaxIdleTime(8 * time.Minute)
    // 設定串連的最大使用時間,避免長時間使用長串連,造成串連不均衡。建議設定為 30 分鐘。
    db.SetConnMaxLifetime(30 * time.Minute)
    
	defer db.Close()

	//定期列印串連池狀態, 用於診斷串連是否夠用,是否存在等待串連,以及串連關閉的次數
	go func() {
		for {
			fmt.Printf("%+v\n", db.Stats())
			time.Sleep(10 * time.Second)
		}
	}()

    
	//擷取資料庫中所有的database
	{
		rows, err := db.Query("show databases")
		if err != nil {
			panic(err.Error())
		}
        defer rows.Close()
		for rows.Next() {
			var dbName string
			err := rows.Scan(&dbName)
			if err != nil {
				panic(err.Error())
			}
			fmt.Println(dbName)
		}
	}

	//建立表
	{
		_, err := db.Exec("create table if not exists user_test(id int, name varchar,age int, primary key(id))")
		if err != nil {
			fmt.Println("create table error ", err)
			return
		}
	}

	//寫入資料

	//寫入方法一:直接寫入資料。
	{
		_, err = db.Exec("upsert into user_test(id,name,age) values(1,'zhangsan',17)")
		if err != nil {
			fmt.Println("insert data error", err)
			return
		}
	}

	//寫入方法二:通過綁定參數的方式進行寫入資料。
	{
		stmt, err := db.Prepare("upsert into user_test(id,name,age) values(?,?,?)")
		if err != nil {
			fmt.Println("prepare error", err)
			return
		}
        defer stmt.Close() 
		_, err = stmt.Exec(2, "lisi", 18)
		if err != nil {
			fmt.Println("upsert error", err)
			return
		}
	}

	//查詢資料

	//查詢方法一:直接查詢資料。

	{
		rows, err := db.Query("select * from user_test")
		if err != nil {
			fmt.Println("query data error", err)
			return
		}
		defer rows.Close()
		var id int
		var name string
		var age int
		for rows.Next() {
			err = rows.Scan(&id, &name, &age)
			if err != nil {
				fmt.Println("scan data error", err)
				return
			}
			fmt.Println("id:", id, "name:", name, "age:", age)
		}
	}

	// 查詢方法二:通過綁定參數的方式執行參數化查詢。
	{
		stmt, err := db.Prepare("select * from user_test where id=?")
		if err != nil {
			fmt.Println("prepare error", err)
			return
		}
        defer stmt.Close()
		rows, err := stmt.Query(1)
		if err != nil {
			fmt.Println("query data error", err)
			return
		}
		defer rows.Close()
		var id int
		var name string
		var age int
		for rows.Next() {
			err = rows.Scan(&id, &name, &age)
			if err != nil {
				fmt.Println("scan data error", err)
				return
			}
			fmt.Println("id:", id, "name:", name, "age:", age)
		}
	}

	//刪除資料
	{
		_, err = db.Exec("delete from user_test where id=1")
		if err != nil {
			fmt.Println("delete data error", err)
			return
		}
	}
}
說明
  • rows使用完成後必須調用Close關閉。

  • 對效能要求較高的情境可以複用Stmt。

  • 在使用QueryContext、ExecContext等與Context相關的介面時,如果設定的逾時時間過短,可能因用戶端記憶體回收(GC)抖動而導致Context逾時進而引發串連重設,影響系統效能。

如果當前執行個體僅有default一個資料庫,執行成功後將返回如下結果:

default
information_schema
id: 1 name: zhangsan age: 17
id: 2 name: lisi age: 18
id: 1 name: zhangsan age: 17