iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
Software Development

MYSQL-相關實務操作學習紀錄系列 第 16

Day.16 應用中學習- 資料庫操作 ( golang / sql )

  • 分享至 

  • xImage
  •  

身處後端開發一定會接觸到寫code去操作資料庫的需求,所以今天主題來介紹一點實務應用,透過Golang操作mysql資料庫,程式如何控制事務的提交與回滾&資料異動操作~

連線資料庫設置

package main

import (
	"database/sql"
	"fmt"

	_ "github.com/go-sql-driver/mysql"
)

func main() {

	//Init connect object.  content-> account:password@tcp(host_ip:port)/db_name
	dbu, err := sql.Open("mysql", "root:1234@tcp(127.0.0.1:3306)/user?charset=utf8&parseTime=True")
	if err != nil {
		fmt.Println("open mysql error", err)
		return
	}

	//close conn.
	defer dbu.Close()

	//Create mysql connect.
	err = dbu.Ping()
	if err != nil {
		fmt.Println("create mysql connect  error", err)
		return
	}

	/*
		>以下連接池設定
		    注意點:
			(1.)mysql連線預設保存時間為8小時,閒置超過8小時會被mysql斷開變失效連線。
				查詢: show variables like '%wait_timeout%';

				注意: 使用到被mysql斷開的連線會產生ERROR -> packets.go:36: unexpected EOF

			(2.)mysql最大連線數。
				查詢: show variables like '%max_connections%';

	*/

	//設置最大併發連線數,超過連線數需等待,直到其中連接被釋放並變為空閒。
	dbu.SetMaxOpenConns(100)
	//設置最大的空閒連接數,適當的設定空閒連接數(會佔用內存)將提高性能,減少從頭建立新連接的可能。
	dbu.SetMaxIdleConns(10)
	//設置連線的生命週期,過期後無法重用。
	dbu.SetConnMaxLifetime(30)
}

(1.)建立資料庫
CREATE DATABASE user;

(2.)建立資料表
CREATE TABLE `user_lists` (
  `user_id` bigint(20) NOT NULL COMMENT '使用者ID',
  `account` varchar(50) NOT NULL COMMENT '帳號',
  `level` tinyint(5) NOT NULL COMMENT '層級',
  `last_login_time` int(11) NOT NULL COMMENT '最後登入時間',
  `create_time` int(11) NOT NULL COMMENT '建立時間',
  PRIMARY KEY (`user_id`)
);

進入正題~透過mysql driver對user_list這張表進行資料存取操作。

  • Exec() -> 執行寫入異動SQL操作。
//異動數據 ( 新增/刪除/更新 )
func ExecSQL(dbu *sql.DB) error {

	//INSERT INTO user_list(user_id,account,level,last_login_time,create_time) values(8723131, "siangx", 1, 1630385990, 1530385990);

	sql := "INSERT INTO user_list(user_id,account,level,last_login_time,create_time) values(?,?,?,?,?)"

	res, err := dbu.Exec(sql, 8723131, "siangx", 1, 1630385990, 1530385990)
	if err != nil {
		fmt.Println("insert user table error", err)
		return err
	}
	//返回執行影響筆數
	count, err := res.RowsAffected()
	if err != nil {
		fmt.Println("get RowsAffected error", err)
		return err
	}
	fmt.Printf("[OK] %d row affected ", count)

	return nil
}
  • Query() -> 執行數據庫查詢操作(多筆) & QueryRow() -> 執行數據庫查詢操作(單筆)。
//查詢數據
func QuerySQL(dbu *sql.DB) {

	//先定義欲搜尋欄位的資料結構
	type User struct {
		UserID  int64
		Account string
		Level   int
	}

	/*
		var userLists User
		//單筆查詢
		if err := dbu.QueryRow("SELECT user_id,account,level FROM user_list WHERE user_id = ?", 8723131).
			Scan(&userLists.UserID, &userLists.Account, &userLists.Level); err != nil {
			fmt.Println("query user table error", err)
		}
		log.Println(userLists)
	*/

	//查詢內容可能包含一筆(含)以上使用Query

	//定義好要回傳的欄位結構
	var userList []User

	//send query sql to mysql
	rows, err := dbu.Query("SELECT user_id,account,level FROM user_list WHERE user_id = ?", 8723131)
	if err != nil {
		fmt.Println("query user table error", err)
	}

	// close sql.Rows -> 重要: 記得要有這個動作去手動釋放連線。
	defer rows.Close()

	//read sql response rows -> 遍歷讀取出來的row資訊存入定義好的User結構
	for rows.Next() {
		user := User{}
		err := rows.Scan(&user.UserID, &user.Account, &user.Level)
		if err != nil {
			fmt.Println("get user row data error", err)
		}
		userList = append(userList, user)
	}

	fmt.Printf("query response: %+v:", userList)
}

最後是我們的Transaction~
還記得前面我們提到用MYSQL CLI手動執行一個事務流程吧,現在換用程式來控制。

複習一下:

  1. 進入交易模式- begin
  2. 本次交易要執行的SQL內容(update/insert....)
  3. 結束交易模式- commit
  • 當交易過程中有發生錯誤時- rollback (表示取消交易,還原到未交易時的狀態)

明天寫一個簡單的應用流程來說明事務提交流程~


上一篇
Day.15 Crash Recovery- InnoDB 架構 -> MYSQL 二階段提交(2PC) _完
下一篇
Day.17 應用中學習 - 實務操作資料庫寫入 ( golang / sql )
系列文
MYSQL-相關實務操作學習紀錄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言