**结论:四条基本都认,只有「缓存进进程内存」这条在 PHP-FPM 下要打个折扣,cast 白名单我再补一个 unsigned BIGINT 的边界。**
cast 这条你说得对,而且比 DECIMAL 更隐蔽的是 unsigned BIGINT:最大值 18446744073709551615 已经越过 PHP_INT_MAX,(int) 会饱和截断,用户 ID 这类字段静默串号。我的处理方式是 int 列先看 DESCRIBE 结果里的 column_type,带 unsigned 就原样留字符串,比较也统一用 ===,不与宽松比较混用,否则 '0'/null 又会造成误判。
DESCRIBE 缓存那里要区分运行模式:传统 FPM 是「每请求一个进程生命周期」,静态属性在请求结束就消失了,你说的进程内存缓存实际只剩单请求内的收益;如果需要在请求之间保留,就要靠 APCu/opcache preload,或者你们本来跑在 Swoole/RoadRunner 常驻进程里。所以我更倾向 per-request 首次用一条 SQL 查 information_schema 拿全表所有列,比逐表 DESCRIBE 少不少往返,「中途加列不生效」的问题自然不存在,dev 的 flush 入口也省了。
LIMIT 和 lastInsertId 都同意,补一刀:内部别用 0 表达「不限制」,用 null 更不容易误判;主键在 PHP 侧生成时注意 exists 和「有没有主键值」是两件事,别因为 id 非空就置 exists = true,否则第一次 save() 会走 UPDATE 打空。UUID 主键还建议用 UUIDv7/ULID 这类有序的,随机 UUID 在 InnoDB 聚簇索引上插入会页分裂。
重试只对 SELECT 也是我最认同的一刀。更省事的做法是从源头降低发生率:长连接加上在 wait_timeout 内定期 ping,别让连接空闲到服务器踢掉。
常见坑: INSERT 真正安全的只有业务幂等键 + 唯一索引兜底,ORM 层别假装能解决。

正式会员
认证极客









