MySQL unsigned int类型数据使用一些事项
以 Signed 为例,可以储存 -2147483648 to 2147483647 而以 Unsigned 为例,可以储存 0 to 4294967295 不过在操作这类栏位的时候,必须要小心,以避免删过头,反而变成补血补满。
正常来讲,MySQL 在操作数字加减的时候,可以这样做
PgSQL
代码如下 | |
-- transaction start-- -- 用程式计算 example 的新值,然后调回去 UPDATE `test` SET `example` = n WHERE ID = :ID; -- 用程式计算 example 的新值,然后调回去 UPDATE `test` SET `example` = n WHERE ID = :ID; -- commit transaction |
不过比较聪明的人,大概都会这样做,以减少 Query 次数 (假设一次减 1)
PgSQL
代码如下 | |
UPDATE `test` SET `example` = `example` - 1; UPDATE `test` SET `example` = `example` - 1; |
不过,上面这行 SQL Statement 有个风险。由於没有做边界检查,所以当 example = 0 的时候,再减掉 1 就会变成 4294967295 。
以下图为例:
这是我自己的页面截图,图中的 Plurk 数达到 4,294,967,294 ,就是 42 亿多笔,假设我一秒发一笔出去,在我有生之年都戳不完 (1 * 86400 * 365 * 100 = 3153600000, 35 亿) 。页面连结
所以,当这个栏位是记录”金额”或是”点数”的时候,就会对资料造成很大的影响 (只要程式 transaction/work flow 没控制好,穷人也可以一夕致富) 。
虽然问题很严重,不过改善的方法也很简单,只要加上 WHERE 条件限制,就可以马上避免掉这个问题。
PgSQL
代码如下 | |
UPDATE `test` SET `example` = `example` - '1' WHERE `example` > 0; UPDATE `test` SET `example` = `example` - '1' WHERE `example` > 0; |
备?:关於这个问题已经回报官方了,不知道这个 BUG 何时会被修正过来