当用数据库存储一个数值,并且这个数值需要被增减的时候,比如物品的数量。
在这种场景下,物品的数量是不能为负数的。那如何确保在扣减这个数量的时候,不会被扣成负数呢。
假设表数据如下:
sku | num |
a | 10 |
b | 20 |
假设现在 a 的 num 要 减少10个。
用程序在操作之前判断? num 是否足够扣减 ? 这明显是不靠谱的。因为有并发的情况存在。
在并发的情况下,a 的 num 会变成 -10 当然,前提你的 sql 是这么写的:
UPDATE table SET num=num-10 WHERE sku="a"
绝对不能用程序去计算 num 的值,在赋值到 sql 中,在并发情况下 num 会变成 0,错误示例:
$data = 'select * from table where sku="a"'; $num = $data['num'] - 10; UPDATE table SET num=$num WHERE sku="a"
所有的方案必须有正确的操作 sql 也就是,第一种 sql。
方案1:
利用数据库的事务,
在 update 的 sql 执行完成后,select num 的值判断是否小于0,如果小于,回滚。
方案2:
更改 num 字段的属性,无符号整形。
即字段属性中的 UN,Unisigned
参考 sql :
ALTER TABLE `table` CHANGE COLUMN `num` `num` INT(11) UNSIGNED NOT NULL DEFAULT '0' ;
这种情况下,当 num 被减成负数的时候,数据库会返回错误。
Error Code: 1690. BIGINT UNSIGNED value is out of range in ....