有个骚操作需要根据订单号扣费,订单号在数据库里是varchar类型,长度64,大概就是和时间戳差不多的纯数字字符串
但是经过测试发现,有一些订单会无缘无故扣费,当时我的SQL语句是这样写的
SQL := fmt.Sprintf("update xxx set count = count + %d,last_up_time = %d where order_id = %s ", money, last_up_time, order_id)
我把每次调用这句SQL的时候都打印出来,发现有一些订单莫名其妙扣了钱都是日志里面没有记录,于是想难道是中出了一个家伙也会操作这张表?问了一波发现没有
通过mysql的binlog查看,发现每一次update某个订单的时候还会顺着update好几个订单,我懵逼
于是把日志打印出来的sql语句亲身执行了一下,发现受影响的行居然大于1 ???
update xxx set count = count + 15,last_up_time = 1524732272 where order_id = 2018042611408321524710026
当时日志的sql如上,问了一波人,发现了把order_id那里要加上引号,就可以正确扣费了
后来google了一波,原来mysql里如果是字符串类型,每当和数字比较,会把字符串转化成int再和数字比较,由于mysql默认最大支持20位int转化,而我们的order_id前面20位是日期时间戳之类的,所以特别容易会重复,于是就GG了
而加上引号之后,这个order_id就变成字符串了,字符串和字符串比较就稳了