安全流程SQL
## GO语法
Update("quota", gorm.Expr("quota + ?", quota))
==>
## 转换就SQL
UPDATE user SET quota = quota + ? WHERE id = ?
Update("quota", gorm.Expr("quota - ?", quota))
==>
UPDATE user SET quota = quota - ? WHERE id = ?
说明
在 MySQL / PostgreSQL 中是:
✔ 原子操作(Atomic)
不会出现“先读再写”的竞态问题
多个请求同时执行时,数据库会串行处理行锁
✔ 行级锁(InnoDB)
同一行(id)会被锁住
并发执行时不会丢失更新
所以不会出现这种问题:
线程A:读 quota=100
线程B:读 quota=100
线程A:写 110
线程B:写 110 ❌(丢失更新)风险点
- quota 可能被扣成负数