事务和锁
注意
使用事务处理,需要数据库引擎支持事务处理。比如 MySQL 的 MyISAM 不支持事务处理,需要使用 InnoDB 引擎。
锁 Lock()
- @param
lockStr
锁类型,默认FOR UPDATE
- 排它锁
FOR UPDATE
- 共享锁
LOCK IN SHARE MODE
- 注意:锁要在事务中使用,不可单独使用
事务 BeginTransaction()
- @param
tg.Source{}
数据源,参数选填,不传默认会读取config/config.yaml
里的数据库配置 - -------@param
Link
数据库连接字符串 - -------@param
Debug
是否打印最终执行的SQL语句,默认不打印 - -------@param
CreateTime
创建时间字段名,默认 create_time - -------@param
UpdateTime
更新时间字段名,默认 update_time - -------@param
DeleteTime
删除时间字段名,默认 delete_time - -------@param
MaxOpen
最大打开连接数 - -------@param
MaxIdle
最大空闲连接数 - -------@param
MaxIdleTime
连接在空闲状态下的最大存活时间 - -------@param
MaxLifeTime
连接的最大生命周期,从创建到被关闭的总时间
事务配合锁解决并发超卖的问题
var goods Goods
tx := tg.BeginTransaction()
err := tx.Db("goods").Where("id", "=", 1).Lock().FindOne(&goods)
if err != nil {
fmt.Println("查询异常")
return
}
if goods.Stock > 0 {
err = tx.Db("goods").Where("id", "=", 1).Decr("stock", 1)
if err != nil {
tx.Rollback()
}
} else {
fmt.Println("库存不足")
}
tx.Commit()
var goods Goods
tx := tg.BeginTransaction()
err := tx.Db("goods").Where("id", "=", 1).Lock().FindOne(&goods)
if err != nil {
fmt.Println("查询异常")
return
}
if goods.Stock > 0 {
err = tx.Db("goods").Where("id", "=", 1).Decr("stock", 1)
if err != nil {
tx.Rollback()
}
} else {
fmt.Println("库存不足")
}
tx.Commit()
最终的SQL语句为:
START TRANSACTION
SELECT * FROM goods WHERE id = 1 FOR UPDATE
UPDATE goods SET stock = stock - 1 WHERE id = 1
COMMIT
START TRANSACTION
SELECT * FROM goods WHERE id = 1 FOR UPDATE
UPDATE goods SET stock = stock - 1 WHERE id = 1
COMMIT