乐观锁与悲观锁是两种常见的并发控制机制,用于解决多用户同时操作同一数据时的一致性问题
一、悲观锁(Pessimistic Locking)
1. 原理
- 假设:并发冲突很可能发生,因此在读取数据时就加锁,防止其他事务修改。
- 适用于写操作频繁、冲突概率高的场景。
2. MySQL 中的实现
通过
SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE(8.0 后推荐用FOR SHARE)实现行级锁(InnoDB 引擎)。
-- 排他锁(写锁):其他事务不能读(除非快照读)、不能写
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
-- 共享锁(读锁):允许多个事务读,但阻止写
SELECT * FROM accounts WHERE id = 1 FOR SHARE;
⚠️ 必须在事务中使用,否则锁会立即释放。
3. Gin + GORM 示例(悲观锁)
func TransferHandler(c *gin.Context) {
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
var fromAccount Account
// 悲观锁:锁定 from 账户
if err := tx.Set("gorm:query_option", ).Where(, ).First(&fromAccount).Error; err != {
tx.Rollback()
c.JSON(, gin.H{: })
}
toAccount Account
err := tx.Set(, ).Where(, ).First(&toAccount).Error; err != {
tx.Rollback()
c.JSON(, gin.H{: })
}
fromAccount.Balance < {
tx.Rollback()
c.JSON(, gin.H{: })
}
fromAccount.Balance -=
toAccount.Balance +=
tx.Save(&fromAccount)
tx.Save(&toAccount)
tx.Commit()
c.JSON(, gin.H{: })
}

