php 8.2下事务仍依赖pdo/mysqli与innodb,关键需设pdo::errmode_exception、mysqli需显式恢复autocommit(true)、readonly类不作用于事务本身。

PHP 8.2 本身不新增事务机制,事务能力仍由底层数据库驱动(PDO/MySQLi)和存储引擎(如 InnoDB)提供。你用 PHP 8.2 写事务代码,和 PHP 7.4 没本质区别——关键在怎么写、怎么防错、怎么适配新特性带来的隐含风险。
pdo::beginTransaction() 必须配合 PDO::ERRMODE_EXCEPTION
PHP 8.2 默认错误模式仍是 PDO::ERRMODE_SILENT,这意味着 SQL 报错不会抛异常,try...catch 捕不到,rollback() 就永远不会执行。
- 必须显式设置:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) - 漏掉这行,哪怕 SQL 语法错、字段不存在、主键冲突,程序都静默跳过,最后
commit()还会照常执行,数据就“半成功”了 - PHP 8.2 对类型更严格,但
setAttribute()调用本身不校验错误模式值是否合法,传错(比如拼成ERRMODE_EXCETPION)也不会报错,只会失效
MySQLi 的 autocommit(FALSE) 容易被忽略恢复
MySQLi 不像 PDO 那样有独立的事务方法,它靠开关自动提交状态。问题在于:一旦开启事务后没正常 commit() 或 rollback(),连接可能带着 autocommit = FALSE 状态进入连接池复用,下一个请求就莫名其妙卡在事务里。
- 务必在事务块末尾强制恢复:
$mysqli->autocommit(TRUE) - 不能只依赖
try/catch—— 如果是 fatal error(如内存溢出、PHP 8.2 的新 strict type crash),catch根本捕不到,autocommit(TRUE)就不会运行 - 更稳妥的做法是:在事务开始前记录原始状态,结束时无条件还原,而不是硬编码设为
TRUE
PHP 8.2 的只读类(readonly class)和事务无关,但容易误用
有人看到 PHP 8.2 新增 readonly class,以为能“让事务对象不可变”,这是典型误解。事务控制逻辑(beginTransaction/commit)操作的是数据库连接资源,不是 PHP 对象属性。
-
readonly class只保护类内部属性不被修改,对数据库状态零影响 - 若把 PDO 实例塞进只读类里,反而可能因构造函数参数校验更严(如 PHP 8.2 对联合类型、空值检查更激进),导致初始化失败
- 真正该用只读类的,是事务中传递的 DTO,比如转账参数:
readonly class TransferRequest { public function __construct(public int $fromId, public int $toId, public float $amount) {} },防止中途被篡改
事务真正的脆弱点不在语法,而在边界:网络中断时 rollback 是否真发出去了?连接超时后 PDO 对象是否还有效?PHP 8.2 的 JIT 和更严格的错误处理会让这些问题暴露得更快,但解决方式没变——加监控、设超时、用连接健康检查,而不是指望语言新特性兜底。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











