golang操作mysql(go-sql-driver 包使用)

go-sql-driver 使用

go-sql-driver 是go用來鏈接mysql數據庫的包。截止當前時間github上star 9.3k

環境:
go go-sql-driver
go1.13.5 v1.5.0
安裝:

使用go mod 進行安裝
在go.mod 中加入:

module github.com/luslin/tools
go 1.13
require (
	github.com/Shopify/sarama v1.26.1
	github.com/gin-gonic/gin v1.6.2
	github.com/go-redis/redis v6.15.7+incompatible
	github.com/go-sql-driver/mysql v1.5.0    // 這一行
	github.com/json-iterator/go v1.1.9
	github.com/tidwall/gjson v1.6.0
	go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738
)

然後執行go mod download 就可以可。 我的GOPROXY設置爲https://goproxy.cn,direct

使用:

我的數據表結構: umeta_id int, user_id int, meta_key vchar, meta_value vchar
a、導入包:

import (
	"context"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"testing"
)

b、創建公共變量,結構體,處理失敗方法

type Wp_usermeta struct {
	Umeta_id int `json:"umeta_id"`
	User_id int `json:"user_id"`
	Meta_key string `json:"meta_key"`
	Meta_value string `json:"meta_value"`
}

var (
	db *sql.DB
	err error
)

func painc_err(err error) {
	if err != nil {
		panic(err)
	}
}

c、初始化db

// The returned DB is safe for concurrent use by multiple goroutines
// and maintains its own pool of idle connections. Thus, the Open
// function should be called just once. It is rarely necessary to
// close a DB. 
//  db是線程安全的,並且在內部維護了數據池。open方法應只調用一次,並且沒必要關閉
func init() {
	// 格式:username:password@鏈接協議(ip:port)/db?參數
	db, err = sql.Open("mysql", "root:fstxlab@2017!@tcp(123.57.174.21:3306)/horizon?charset=utf8")
	painc_err(err)
}

d、curd
1、查詢單條記錄

func TestQueryRow(t *testing.T) {
	stmt, err := db.Prepare("select * from wp_usermeta where umeta_id = ?")
	defer stmt.Close()
	painc_err(err)
	res:= stmt.QueryRow(12)
	var usermeta Wp_usermeta
	err = res.Scan(&usermeta.Umeta_id, &usermeta.User_id, &usermeta.Meta_key, &usermeta.Meta_value)
	painc_err(err)
	fmt.Println(usermeta)
}

2、查詢多條記錄

func TestQueryRows(t *testing.T) {
	stmt, err := db.Prepare("select * from wp_usermeta where umeta_id < ?")
	defer stmt.Close()
	painc_err(err)
	res, err := stmt.Query(12)
	defer res.Close()
	painc_err(err)
	for res.Next() {
		var usermeta Wp_usermeta
		err = res.Scan(&usermeta.Umeta_id, &usermeta.User_id, &usermeta.Meta_key, &usermeta.Meta_value)
		painc_err(err)
		fmt.Println(usermeta)
	}
}

3、插入數據

func TestInsert(t *testing.T)  {
	stmt, err := db.Prepare("insert into wp_usermeta(user_id,meta_key,meta_value) value (?,?,?)")
	painc_err(err)
	defer stmt.Close()
	res, err := stmt.Exec(2,"test3","test4")
	painc_err(err)
	row_num, err := res.RowsAffected()
	painc_err(err)
	fmt.Println(row_num)
}

4、修改數據

func TestUpdate(t *testing.T)  {
	stmt, err := db.Prepare("update wp_usermeta set user_id=? where user_id=?")
	painc_err(err)
	defer stmt.Close()
	res, err := stmt.Exec(1,2)
	painc_err(err)
	row_num, err := res.RowsAffected()
	painc_err(err)
	fmt.Println(row_num)
}

5、刪除數據

func TestDelete(t *testing.T)  {
	stmt, err := db.Prepare("delete from wp_usermeta  where umeta_id=?")
	painc_err(err)
	defer stmt.Close()
	res, err := stmt.Exec(27)
	painc_err(err)
	row_num, err := res.RowsAffected()
	painc_err(err)
	fmt.Println(row_num)
}

e、事務

func TestTxn(t *testing.T) {
	txn := sql.TxOptions{sql.LevelRepeatableRead,false}
	tx, err := db.BeginTx(context.Background(),&txn)
	painc_err(err)
	stmt1, err := tx.Prepare("delete from wp_usermeta  where umeta_id=?")
	painc_err(err)
	defer stmt1.Close()
	res, err := stmt1.Exec(30)
	painc_err(err)
	row_num, err := res.RowsAffected()
	painc_err(err)
	fmt.Println(row_num)
	//err = tx.Commit()
	//painc_err(err)
	err = tx.Rollback()
	painc_err(err)
}

Commit不能與Rollback同時使用
事務屬性的結構:

type TxOptions struct {
	// Isolation is the transaction isolation level.
	// If zero, the driver or database's default level is used.
	Isolation IsolationLevel
	ReadOnly  bool
}

Isolation 代表事務隔離級別,有以下幾種:

	LevelDefault IsolationLevel = iota  默認
	LevelReadUncommitted
	LevelReadCommitted
	LevelWriteCommitted
	LevelRepeatableRead
	LevelSnapshot
	LevelSerializable
	LevelLinearizable

參考:https://www.cnblogs.com/wyaokai/p/10921323.html
1、髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據
2、不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。
3、幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改爲ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。
  小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表

事務隔離級別 髒讀 不可重複讀 幻讀
讀未提交ReadUncommitted
不可重複讀ReadCommitted
可重複讀RepeatableRead
串行化Serializable
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章