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

猜你喜欢

转载自blog.csdn.net/luslin1711/article/details/105900708