先贴一个看云手册,关于事务:https://www.kancloud.cn/manual/thinkphp5/139063。
使用事务处理的话,需要数据库引擎支持事务处理。比如 MySQL 的 MyISAM 不支持事务处理,需要使用 InnoDB 引擎
我在ThinkPHP5.0.22版本中,在操作数据库前开启了手动事务处理:
// 开始多表插入事务处理
Db::startTrans();
$banner_data = ['banner_id' => 1,'goods_id' => $goodsID,'create_time' => date('Y-m-d H:i:s')];
Db::name('banner')->insertGetId(['goods_id' => $goodsID,'create_time' => date('Y-m-d H:i:s')]);
$banner = Db::name('banner')->insertGetId($banner_data);
if(!$banner) {
echo "banner发生回滚\n";
echo $banner;
Db::rollback();
} else {
// 否则提交
Db::commit();
}
我使用了两次insertGetId(),执行完毕会返回插入记录的主键,第一次使用insertGetId()时并没有指定主键值,主键会自增插入。第二次使用insertGetId()时,我指定了主键banner_id = 1。该主键在数据库banner表中已经存在。不出意外的话会发生回滚,banner表不会有任何数据插入。
banner表,代码执行前:
banner表,代码执行后:
不应该被提交的第一次插入执行了!!!文档中提到mysql需要innoDB引擎支持,检查一波数据库引擎:
运行mysql命令:show engines;
再检查表所用的引擎:
运行msql命令: show create table 表名;
show create table banner;
也可以使用:
show table status;(不过要注意使用时是否正在使用目标数据库,否则记得在后面加上from 数据库名)
发现banner表并没有用innoDB引擎,盲猜把它改用innoDB引擎就好了?我的数据库中没什么数据,就直接简单粗暴的直接该更改引擎类型了。虽然更改完后该表数据还在,但是更改的时候会引发大量IO操作,应该是表中有多少条数据就会有多少次IO操作,其他数据库有大量数据的请谨慎操作!!!
alter table banner ENGINE = InnoDB;
更改完毕记得重启数据库,然后我把banner表恢复到只有一条记录的时候:
再次执行代码:
生效了,nice!!! 如果想抛出自定义异常的话,就使用try{}catch{}:
// 开始多表插入事务处理
Db::startTrans();
try {
$banner_data = ['banner_id' => 1,'goods_id' => $goodsID,'create_time' => date('Y-m-d H:i:s')];
Db::name('banner')->insertGetId(['goods_id' => $goodsID,'create_time' => date('Y-m-d H:i:s')]);
$banner = Db::name('banner')->insertGetId($banner_data);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
// throw Exception('数据库操作异常');
throw Exception($e);
}