golang mysql对比db+事务tx

go语言 同时被 2 个专栏收录
31 篇文章 0 订阅
12 篇文章 0 订阅
事务

事务处理是数据的重要特性,对于一些支付系统,事务对业务逻辑会有重要影响。golang的mysql驱动也封装好了事务相关的操作,一般使用的是db对象的方法,事务则是使用另外一个对象,sql.Tx对象。

使用db的Begin方法可以创建tx对象,用法和db的相关用法类似。一旦创建了tx对象,事务处理都依赖与tx对象,这个对象会从连接池中取出一个空闲的连接,接下来的sql执行都基于这个连接,直到commit或者rollback调用之后,才会把连接释放到连接池。

在事务处理的时候,不能使用db的查询方法,虽然后者可以获取数据,可是这不属于同一个事务处理,将不会接受commit和rollback的改变,事务的连接生命周期从Beigin函数调用起,直到Commit和Rollback函数的调用结束

db和tx初始化

package mysqltx

type Ip struct {
	UUID string `gorm:"column:id" json:"uuid"`
	IP   string `gorm:"column:ip" json:"ip"`
	MAC  string `gorm:"column:mac" json:"mac"`
}

func (User) TableName() string {
	return "ips"
}

// *** 通过tx的方式初始化数据库 ***
	tx := db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	// 查询
	var ips []Ip
	err := tx.Where("uuid = ?","3333feeb52eb425593231247fead95c5").Find(&ips).Error

	// 创建
	ip := &Ip{UUID:"3333feeb52eb425593231247fead95c5",IP:"192.168.1.1"}
	err := tx.Create(ip).Error

	//删除
	ip := &Ip{UUID:"3333feeb52eb425593231247fead95c5",IP:"192.168.1.1"}
	err := tx.Delete(ip).Error

	//提交,注意对tx创建操作后一定要commit,否则程序不会报错,但数据库也未创建成功
	err := tx.Commit().Error



// *** 通过db的方式初始化数据库 ***
import "github.com/jinzhu/gorm"

var db *gorm.DB
func initdb() {
	// 第一个参数:数据库类型(mysql,postgres)
	// 第二个参数:数据库连接,用户名:密码@protocal(ip:port)
	conn := "root:root@tcp(192.168.1.12:3306)?charset=Utf8&parseTime=true&loc=Local"
	db,err := gorm.Open("mysql", conn)
	defer db.Close()
	
	//SetMaxOpenConns用于设置最大打开的连接数
    //SetMaxIdleConns用于设置闲置的连接数
    db.DB().SetMaxIdleConns(10)
    db.DB().SetMaxOpenConns(100)
}

db和tx对比

// 对比db和tx查询
rows, _ := db.Query("SELECT uuid FROM ips") 
for rows.Next() {
    var mid, did int
    rows.Scan(&mid)
    db.QueryRow("SELECT id FROM detail_user WHERE master = ?", mid).Scan(&did)
}

调用了Query方法之后,在Next方法中取结果的时候,rows是维护了一个连接,再次调用QueryRow的时候,db会再从连接池取出一个新的连接。rows和db的连接两者可以并存,并且相互不影响。但若失通过tx的方式实现时无法实现二次查询的,因为第一次的查询并没有被释放,无法执行下一次查询

场景分析

func delete(){
	//1、通过事务删除一条数据
	ip := &Ip{UUID:"3333feeb52eb425593231247fead95c5",IP:"192.168.1.1"}
	err := tx.Delete(ip).Error
	
	//2、通过db查询该数据
	ip := Ip{}
	err := db.Where("uuid= 3333feeb52eb425593231247fead95c5").First(&ip)
}

上述情况仍在数据库查询到数据,因为删除是通过事务完成的,查询是通过db,调用的不是同一个连接,导致数据不同步,所以建议一个处理流程中选择完整的tx或db,不要穿插使用

  • 3
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值