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