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
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现