记录mysql字段相减遇到的问题
2023-03-07 20:18:15

最近像往常一样在写代码,但是今天却被一个bug卡了2小时。
但是实际上是个非常简单的需求:用户消费从用户钱包扣除对应消费的金额。
其中amount字段是bigint 但是没有设置unsigned 因为可以为负数

用sql表示就是

1
update merchant_wallets set amount = amount - 100 where id = 1;

用gorm的代码实例试下

1
2
3
var consume uint64 = 100;

gorm.Model(&wallet).UpdateColumn("amount",gorm.Expr("amount - ?",consume))

用sql在mysql里执行是可以成功执行的 但是在go里用gorm更新,报错1690:amount Bigint Unsigned out of range,但是我反复确认amount字段并不是unsigned,以为是gorm的bug,还跑去github提issue。

最后发现其实是consume字段是uint64,mysql有个隐藏机制:MySQL处理两个整数(INT)相减的时候,如果其中有一个是UNSIGNED INT类型的,那么结果就被当做是UNSIGNED的,导致amount被当作unsigned 从而导致更新失败