先貼一個看雲手冊,關於事務: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);
}