• 数据库事务transaction


    1.什么是事务?

    数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。--百度百科

    例如,转账就是一个事务,它由两个操作组成:

    • 将款项从第一个账户划出。
    • 将款项存入第二个账户。

    这两个操作要不全部成功,要不全部不成功。
    如果第一个操作成功了,而第二个操作失败了,就需要回滚第一个操作。
    从而保证数据一致性。

    2.golang中对事务的支持

    在golang 编程语言中,database/sql包提供了接口的支持。

    实际上,一个事务就是一个对象,它占用一个到数据库的连接。一个事务中的所有操作,都保证在同一个连接上执行。

    一个事务通过tx, err = db.Begin()创建,通过tx.Commit()tx.Rollback()关闭。
    Tx会从连接池中获取一个连接,事务中所有操作都在这个连接上执行。

    在事务中执行的操作,都要使用Tx变量,不要再使用db变量,db变量不属于事务范围,会使用不同的连接。

    如果执行的多个语句,其中涉及修改连接状态,这时应该使用事务。

    修改连接状态的情况有:

    • 创建临时表(仅对一个连接可见)
    • 修改变量,例如 SET @var := somevalue
    • 修改连接选项,例如 字符集 或 超时时间

    以上任何操作,都需要绑定到连接。因此需要使用事务。

    事务的基本操作包括:

    开启事务

    func (db *DB) Begin() (*Tx, error)
    

    开启一个事务,隔离级别使用driver的默认事务级别。更多事务配置可以使用BeginTx

    执行更新操作

    func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)
    

    例如,update, insert。

    提交

    func (tx *Tx) Commit() error
    

    回滚

    func (tx *Tx) Rollback() error
    

    下面举例说明具体使用方法。

    例子

    例子中,会执行两个update的sql,这两个操作放在一个事务中,保证要么同时更新成功,要么同时更新失败。

    package main
    
    import (
            "database/sql"
            "log"
            "time"
    
            _ "github.com/go-sql-driver/mysql"
    )
    
    var DB *sql.DB
    var dataBase = "root:Aa123456@tcp(192.168.0.101:3306)/?timeout=5s&readTimeout=6s"
    
    func mysqlInit() {
            var err error
            DB, err = sql.Open("mysql", dataBase)
            if err != nil {
                    log.Fatalln("open db fail:", err)
            }
    }
    
    func main() {
            mysqlInit()
    
            TryTransaction(DB)
    }
    
    func TryTransaction(db *sql.DB) (sql.Result, error) {
    	tx, err := db.Begin()
    	if err != nil {
    		return nil, err
    	}
    
    	sql := "update t set count=6 where id=1"
    	res, err := tx.Exec(sql)
    	if err != nil {
    		if err2 := tx.Rollback(); err2 != nil {
    			return res, fmt.Errorf("err:%s, err2:%s", err, err2)
    		}
    		return res, err
    	}
    
    	sql = "update t set count=10 where id=2"
    	res, err = tx.Exec(sql)
    	if err != nil {
    		if err2 := tx.Rollback(); err2 != nil {
    			return res, fmt.Errorf("err:%s, err2:%s", err, err2)
    		}
    		return res, err
    	}
    
    	if err := tx.Commit(); err != nil {
    		return nil, err
    	}
    
    	return res, nil
    }
    

    3.参考

    database/sql--Tx

    Modifying Data and Using Transactions

    Just try, don't shy.
  • 相关阅读:
    广佛肇城轨年内通车 佛山西站预计2017年中通车
    MTK+Android编译
    电量检测芯片BQ27510使用心得
    放大电路的分析方法
    放大电路的分析方法
    模拟电子放大电路分析
    模拟电子技术二极管
    unsigned 整型实现无溢出运算
    hdu 5317 RGCDQ(前缀和)
    CodeForces 429 B Working out(递推dp)
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/14459006.html
Copyright © 2020-2023  润新知