すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:Go-MySQL-Driver を使用して ApsaraDB RDS for MySQL インスタンスに接続する

最終更新日:Mar 12, 2025

アプリケーションで Go プログラミング言語を使用しており、ApsaraDB RDS for MySQL インスタンスへの接続を頻繁に確立する必要がある場合 (短期間の接続など)、またはアプリケーションと RDS for MySQL インスタンス間の接続数が制限を超えている場合は、Go-MySQL-Driver を使用して RDS インスタンスに接続できます。 これにより、アプリケーションが RDS インスタンスに接続する頻度を減らし、RDS インスタンスのメインスレッドのオーバーヘッドを削減できます。 このトピックでは、Go-MySQL-Driver を使用して RDS インスタンスに接続する方法と、接続された RDS インスタンスのデータベースで操作を実行する方法について説明します。

説明

Go-MySQL-Driver は、Go が提供するサードパーティのデータベースドライバパッケージです。 Go-MySQL-Driver を使用して、MySQL および MariaDB データベースに接続できます。

制限事項

Go-MySQL-Driver を使用して接続できるのは、MySQL 5.7 または 8.0 を実行する RDS インスタンスのみです。

準備

  • Go 1.20 以降がインストールされています。 詳細については、「ダウンロードとインストール」をご参照ください。

  • クライアントの IP アドレスが RDS インスタンスの IP アドレスホワイトリストに追加されています。 詳細については、「IP ホワイトリストを構成する」をご参照ください。

    説明

    RDS インスタンスと同じリージョンおよび VPC (仮想プライベートクラウド) にある ECS (Elastic Compute Service) インスタンスにアプリケーションがデプロイされている場合は、IP アドレスホワイトリストを構成する必要はありません。

Go-MySQL-Driver を使用して RDS インスタンスに接続する

1. 依存関係を追加する

  1. go-sql-driver 依存関係を Go プロジェクトの go.mod ファイルに追加します。

    require (
        github.com/go-sql-driver/mysql v1.8.1
    )
  2. 必要なパッケージを .go ファイルにインポートします。

    import (
        // 一般的な SQL インターフェースを提供する database/sql パッケージをインポートします。
        "database/sql"
        // フォーマットされた入出力機能を提供する fmt パッケージをインポートします。
        "fmt"
        // RDS for MySQL のデータベースに接続して管理するために、Go-MySQL-Driver をインポートします。
        "github.com/go-sql-driver/mysql"
        // 時間関連の操作を処理するために、time パッケージをインポートします。
        "time"
    )

2. 接続プールを初期化する

.go ファイルの main メソッドを使用して、接続プールを初期化し、関連パラメータを構成します。 サンプルコード:

// データベース接続を確立します。
cfg := mysql.NewConfig()
cfg.User = "****" // RDS インスタンスへのログインに使用するアカウントのユーザー名で値を置き換えます。
cfg.Passwd = "****" // アカウントのパスワードで値を置き換えます。
cfg.Net = "tcp" // 接続タイプはデフォルトで TCP です。 値を変更する必要はありません。
cfg.Addr = "rm-2zefwjx1s8156******.mysql.rds.aliyuncs.com:3306" // RDS インスタンスのエンドポイントとポート番号で値を置き換えます。
cfg.DBName = "****" // RDS インスタンスの名前で値を置き換えます。

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("データベース接続を閉じるときにエラーが発生しました: %v\n", err)
    }
}(db)
// 接続プールに関連するパラメータを構成します。
db.SetMaxOpenConns(20)   // 接続プール内のオープン接続の最大数を指定します。 ビジネス要件に基づいて値を変更できます。
db.SetMaxIdleConns(2)    // 接続プール内のアイドル接続の最大数を指定します。 ビジネス要件に基づいて値を変更できます。
db.SetConnMaxIdleTime(10 * time.Second)   // 接続プール内の接続がアイドル状態を維持できる最大期間を指定します。 ビジネス要件に基づいて値を変更できます。
db.SetConnMaxLifetime(80 * time.Second)   // 接続を再利用できる最大期間を指定します。 ビジネス要件に基づいて値を変更できます。
説明

RDS インスタンスのエンドポイントとポート番号を表示する方法の詳細については、「インスタンスのエンドポイントとポートを表示および管理する」をご参照ください。

付録: 接続プールの主要パラメータ

重要
  • データベースのランタイムリスクを軽減するために、推奨構成 の表のパラメータを構成することをお勧めします。 また、データベースのパフォーマンスを向上させるために、オプションの構成 の表のパラメータを構成することもできます。

  • 潜在的なリスクと不確実性を最小限に抑え、システムの安定性と信頼性を確保するために、本番環境に新しいパラメータ値を適用する前に、完全な機能テストとパフォーマンステストを実行することをお勧めします。

推奨構成

パラメータ

説明

デフォルト値

推奨値

備考

maxIdleTime

接続の最大アイドル期間。 単位: 分。

0

10~30

  • デフォルト値 0 は、接続がタイムアウトしないことを指定します。

  • 実際の要件に基づいて、アプリケーション用にこのパラメータを構成することをお勧めします。 SetConnMaxIdleTime メソッドを使用してパラメータを構成できます。

maxLifetime

接続を再利用できる最大期間。 単位: 時間。

0

1~8

  • デフォルト値 0 は、接続が常に再利用可能であり、制限が課されないことを指定します。

  • このパラメータは、長期間の接続を防ぎ、リソースを節約するために使用されます。 SetConnMaxLifetime メソッドを使用してパラメータを構成できます。

maxOpen

接続プール内の接続の最大数。

0

100

  • デフォルト値 0 は、制限が課されないことを指定します。

  • MaxIdleConns パラメータの値が 0 より大きく、MaxOpenConns パラメータの新しい値より大きい場合、MaxIdleConns パラメータの値は MaxOpenConns パラメータの制限を満たすように減らされます。

  • 実際の要件に基づいて、アプリケーション用にこのパラメータを構成することをお勧めします。 SetMaxOpenConns メソッドを使用してパラメータを構成できます。

maxIdleCount

接続プール内のアイドル接続の最大数。

2

20

  • このパラメータを構成して、特定の数の接続を予約し、データベースリクエストのバーストに迅速に対応できます。

  • MaxOpenConns パラメータの値が 0 より大きく、MaxIdleConns パラメータの新しい値より小さい場合、MaxIdleConns の新しい値は MaxOpenConns パラメータの制限を満たすように減らされます。

  • SetMaxIdleConns メソッドを使用してパラメータを構成できます。

  • パラメータを 0 以下の値に設定すると、アイドル接続は閉じられます。

readTimeout

I/O 読み取りのタイムアウト期間。 ビジネス要件に基づいて、ミリ秒 (ms)、秒 (s)、または分 (m) で値を指定できます。

0

10000ms~60000ms

  • デフォルト値 0 は、タイムアウト制限が課されないことを指定します。 デフォルト値を保持することをお勧めします。 ビジネス要件に基づいて値を変更できます。

  • このパラメータを、Go の time パッケージで定義されている time.Duration 型によって提供される事前定義された単位定数に設定します。 例: cfg.readTimeout = 30*time.Second。 このパラメータを「30s」などの文字列に設定しないでください。

writeTimeout

I/O 書き込みのタイムアウト期間。 ビジネス要件に基づいて、ミリ秒 (ms)、秒 (s)、または分 (m) で値を指定できます。

0

10000ms~60000ms

  • デフォルト値 0 は、タイムアウト制限が課されないことを指定します。 デフォルト値を保持することをお勧めします。 ビジネス要件に基づいて値を変更できます。

  • このパラメータを、Go の time パッケージで定義されている time.Duration 型によって提供される事前定義された単位定数に設定します。 例: cfg.writeTimeout = 30*time.Second。 このパラメータを「30s」などの文字列に設定しないでください。

オプションの構成

パラメータ

説明

デフォルト値

推奨値

備考

timeout

接続を確立するためのタイムアウト期間。 ビジネス要件に基づいて、ミリ秒 (ms)、秒 (s)、または分 (m) で値を指定できます。

デフォルト値は、オペレーティングシステムのデフォルト値によって異なります。

3000ms

  • このパラメータを、Go の time パッケージで定義されている time.Duration 型によって提供される事前定義された単位定数に設定します。 例: cfg.timeout = 30*time.Second。 このパラメータを「30s」などの文字列に設定しないでください。

  • 接続プールを構成する場合は、1 秒から 10 秒の範囲でタイムアウト期間を指定することをお勧めします。 タイムアウト期間は、ネットワーク品質とアプリケーションとサーバー間の距離によって異なります。

データベースで操作を実行する

テーブルを作成する

この例では、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("テーブルの作成エラー ", err)
    return
}

テーブルにデータを書き込む

この例では、userinfo テーブルにデータが書き込まれます。

方法 1: テーブルに直接データを書き込む

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)

方法 2: パラメータ化クエリを実行してテーブルにデータを書き込む

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)

データを更新する

この例では、userinfo テーブルのデータが更新されます。

stmtUpdate, err := db.Prepare("UPDATE userinfo SET username=?, departname=?, created=?  WHERE username=?")
if err != nil {
    fmt.Println("更新ステートメントの準備エラー:", err)
    return
}
resUpdate, err := stmtUpdate.Exec("Robert", "Sales", "2024-09-23", "Linda")
if err != nil {
    fmt.Println(err)
}
rowCnt, _ := resUpdate.RowsAffected()
fmt.Println(rowCnt)

データをクエリする

この例では、userinfo テーブルから、username フィールドの値が Robert であるデータレコードがクエリされます。

方法 1: 直接データをクエリする

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)

方法 2: パラメータ化クエリを実行してデータをクエリする

stmtQuery, err := db.Prepare("SELECT username,departname,created FROM userinfo WHERE username=?")
if err != nil {
    fmt.Println("準備エラー", err)
    return
}
rowData, err := stmtQuery.Query("Robert")
if err != nil {
    fmt.Println("データのクエリエラー", 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)

データを削除する

この例では、userinfo テーブルから、username フィールドの値が James であるデータレコードが削除されます。

delStmt, _ := db.Prepare("DELETE FROM userinfo WHERE username=?")
resultDel, err := delStmt.Exec("James")
if err != nil {
    panic(err)
}
rowAffect, _ := resultDel.RowsAffected()
fmt.Println("データの削除が完了しました。", rowAffect)

package main

import (
    // 一般的な SQL インターフェースを提供する database/sql パッケージをインポートします。
    "database/sql"
    // フォーマットされた入出力機能を提供する fmt パッケージをインポートします。
    "fmt"
    // RDS for MySQL のデータベースに接続して管理するために、Go-MySQL-Driver をインポートします。
    "github.com/go-sql-driver/mysql"
    // 時間関連の操作を処理するために time パッケージをインポートします。
    "time"
)

func main() {
    // データベース接続を確立します。
    cfg := mysql.NewConfig()
    cfg.User = "****"                                                   /*RDS インスタンスにログインするために使用するアカウントのユーザー名で値を置き換えます。*/
    cfg.Passwd = "****"                                                 /*アカウントのパスワードで値を置き換えます。*/
    cfg.Net = "tcp"                                                     /*接続タイプはデフォルトで TCP です。値を変更する必要はありません。*/
    cfg.Addr = "rm-2ze1vw17v542q6b****.mysql.pre.rds.aliyuncs.com:3306" /*RDS インスタンスのエンドポイントとポート番号で値を置き換えます。*/
    cfg.DBName = "****"                                                 /*データベースの名前で値を置き換えます。*/
    cfg.Timeout = 3 * time.Second                                       /*データベースへの接続を確立するためのタイムアウト期間を指定します。ビジネス要件に基づいて、ミリ秒 (ms)、秒 (s)、または分 (m) で値を指定できます。*/
    cfg.ReadTimeout = 60 * time.Second                                  /*I/O 読み取りのタイムアウト期間。ビジネス要件に基づいて、ミリ秒 (ms)、秒 (s)、または分 (m) で値を指定できます。*/
    cfg.WriteTimeout = 60 * time.Second                                 /*I/O 書き込みのタイムアウト期間。ビジネス要件に基づいて、ミリ秒 (ms)、秒 (s)、または分 (m) で値を指定できます。*/

    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("データベース接続を閉じるときにエラーが発生しました: %v\n", err)
        }
    }(db)

    // 接続プールに関連するパラメータを構成します。
    db.SetMaxOpenConns(100)                 /*接続プール内のオープン接続の最大数を指定します。*/
    db.SetMaxIdleConns(20)                  /*接続プール内のアイドル接続の最大数を指定します。*/
    db.SetConnMaxIdleTime(10 * time.Minute) /*接続プール内の接続がアイドル状態を維持できる最大期間を指定します。*/
    db.SetConnMaxLifetime(8 * time.Hour)   /*接続を再利用できる最大期間を指定します。*/

    // 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("テーブルの作成エラー ", err)
        return
    }

    // テーブルに直接データを書き込みます。
    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)

    // パラメータ化クエリを実行してテーブルにデータを書き込みます。
    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)

    // テーブルのデータを更新します。
    stmtUpdate, err := db.Prepare("UPDATE userinfo SET username=?, departname=?, created=?  WHERE username=?")
    if err != nil {
        fmt.Println("更新ステートメントの準備エラー:", err)
        return
    }
    resUpdate, err := stmtUpdate.Exec("Robert", "Sales", "2024-09-23", "Linda")
    if err != nil {
        fmt.Println(err)
    }
    rowCnt, _ := resUpdate.RowsAffected()
    fmt.Println(rowCnt)

    // テーブルにデータを直接クエリします。
    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)

    // パラメータ化クエリを実行してテーブルにデータをクエリします。
    stmtQuery, err := db.Prepare("SELECT username,departname,created FROM userinfo WHERE username=?")
    if err != nil {
        fmt.Println("準備エラー", err)
        return
    }
    rowData, err := stmtQuery.Query("Robert")
    if err != nil {
        fmt.Println("データのクエリエラー", 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)

    // テーブルからデータを削除します。
    delStmt, _ := db.Prepare("DELETE FROM userinfo WHERE username=?")
    resultDel, err := delStmt.Exec("James")
    if err != nil {
        panic(err)
    }
    rowAffect, _ := resultDel.RowsAffected()
    fmt.Println("データの削除が完了しました。", rowAffect)
}

参照