DECIMAL能彻底避免0.1+0.2≠0.3的误差,而DOUBLE因基于IEEE 754二进制浮点表示,无法精确存储十进制小数(如0.1在二进制中为无限循环小数),必须截断导致初始失真,后续计算误差累积放大,故算钱必然出错。

DECIMAL 能彻底避免 0.1 + 0.2 ≠ 0.3 这类误差,而 DOUBLE 永远做不到——这不是配置问题,是二进制浮点表示法的硬伤。
为什么 DOUBLE 算钱一定会出错?
DOUBLE 把十进制小数转成二进制近似存储,像 0.1 在二进制里是无限循环小数(0.0001100110011...),必须截断,一存就失真。MySQL 执行 SELECT 0.1 + 0.2,结果常是 0.30000000000000004;而 DECIMAL(10,2) 内部按十进制逐位运算,结果严格为 0.30。
这不是“偶尔不准”,而是每次涉及非 2 的幂分母小数(如 0.01、0.05、0.1、0.2)时都必然发生。累计加减、乘除、四舍五入后,误差还会放大。
DECIMAL(M,N) 的 M 和 N 怎么设才安全?
不显式指定 M 和 N 就用默认 DECIMAL(10,0),小数全被截掉——这是线上事故高发点。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 电商价格常用
DECIMAL(10,2):最大支持 99999999.99,覆盖绝大多数商品 - 含税率、佣金或跨境结算场景,建议
DECIMAL(12,4):留足小数位防中间计算溢出 -
M不能超 65(MySQL 极限),N最大 30,但N越大,存储开销和计算耗时越明显 - 别为了“以后可能用上”盲目设大,比如
DECIMAL(20,10)对普通订单纯属冗余
上线后改 DECIMAL 精度有多麻烦?
ALTER COLUMN 修改 DECIMAL 的 M 或 N 会触发全表重写,锁表时间与数据量正相关——百万级表可能卡住业务十几分钟。
常见翻车场景:
- 建表时写成
DECIMAL没带参数,上线后发现小数全丢了 - 初期用
DECIMAL(8,2),半年后要支持 1000 万以上单价,再扩M只能停服操作 - 不同服务对同一字段的精度假设不一致(比如 A 服务按
DECIMAL(10,2)解析,B 服务却按DECIMAL(10,4)写入),数值被静默截断
真正难的不是选 DECIMAL,而是从第一行 DDL 就把 M 和 N 定准,并让所有上下游服务对这个定义达成共识——精度一旦写死,改起来比换数据库还疼。

















