必须使用InnoDB引擎并配合事务实现原子性导入:先预校验Excel数据合法性,再在事务中批量插入,任一失败即回滚;文件操作和API调用须在事务提交后单独处理。

导入失败时整个班级数据必须全部撤销
PHP 导入班级通信录时,如果中途某条记录出错(比如学号重复、手机号格式错误、数据库唯一键冲突),不能只跳过这一条——否则会留下脏数据,后续查询或导出都可能异常。必须让 INSERT 操作具备原子性:全成功,或全不生效。
关键不是“手动删已插数据”,而是从一开始就在事务中执行:
- 调用
mysqli_begin_transaction()或$pdo->beginTransaction()开启事务 - 循环插入每条学生记录,任一
execute()返回false就立即rollback() - 全部成功才
commit();哪怕最后一条失败,前面所有也自动回滚
Excel 解析后批量写入前要预校验字段
很多人把校验逻辑放在 SQL 插入时靠数据库报错触发回滚,这不可靠——比如手机号长度检查、班级编号是否存在、性别值是否为「男/女」,这些本该在 PHP 层拦截,而不是等 INSERT 被 UNIQUE 或 CHECK 拦下再回滚。后者既慢,又让事务持续时间变长,增加锁表风险。
推荐做法是解析完 Excel 后、进事务前做一次轻量级预检:
立即学习“PHP免费学习笔记(深入)”;
- 遍历
$students数组,对每项调用filter_var($phone, FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^1[3-9]\d{9}$/']]) - 用
in_array($class_id, $valid_class_ids)确认班级存在(提前查好并缓存) - 发现任意一条不合法,直接返回错误,根本不上事务
事务中避免调用外部 API 或文件操作
班级通信录导入常伴随“上传头像→保存路径→写入数据库”流程。如果把 move_uploaded_file() 或调用微信接口发通知放在事务里,会导致严重问题:事务回滚只影响数据库,但文件已上传、消息已发出,无法撤回。
正确拆分方式是:
- 第一步:纯数据库操作(含事务)—— 插入学生主表 + 关联表,失败则整体回滚
- 第二步:仅当事务
commit成功后,再单独处理文件移动、生成缩略图、发通知等副作用操作 - 若第二步失败,至少数据库状态干净,可人工补救,不会出现「人已入库但头像丢失」这种不一致
MySQL 引擎必须是 InnoDB 才支持事务回滚
这是最容易被忽略的底层前提。如果班级表用的是 MyISAM 引擎,无论 PHP 代码怎么写 begin/rollback,都只是空转——ROLLBACK 不起作用,数据照样落盘。
检查和修复方法很简单:
- 执行
SHOW CREATE TABLE class_student;,确认引擎显示为ENGINE=InnoDB - 如果不是,运行
ALTER TABLE class_student ENGINE = InnoDB; - 注意:大表执行
ALTER会锁表,建议在低峰期操作
没确认引擎就写事务逻辑,等于给回滚功能装了个假开关。











