安全流程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  ❌(丢失更新)

风险点

  1. quota 可能被扣成负数