一、概述
關於TP5.1框架下mysql數據庫事務操作進行一些簡單使用測試。
注:只是自己本地進行的簡單測試,爲了驗證TP5調用數據庫事務操作的一些注意點,不是太嚴謹。
二、測試環境
TP:5.1.38 LTS
PHP:7.3.4
Apache:2.4.39
MySQL:5.5.29
三、測試數據表
test1
CREATE TABLE `test1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
test2
CREATE TABLE `test1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
四、測試代碼
1. 測試啓用事務操作後,不執行 commit() 而直接退出執行代碼。
測試代碼:
/*
* 數據庫事務測試
*/
public function transactionTest1() {
$content = 'fun1';
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => $content]);
// 直接退出執行
exit();
// 提交事務
// Db::commit();
}
執行結果:test1表並沒有新增數據記錄。
測試結論:在代碼中啓用事務操作後,不執行 commit 而直接退出的話,startTrans 後的sql操作沒有成功執行,數據庫自動進行了rollback處理。
2. 啓用事務並執行 rollback 後,再次進行事務操作。
測試代碼:(注意先重建數據表)
/*
* 數據庫事務測試
*/
public function transactionTest1() {
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => 'p1']);
// 回滾事務
Db::rollback();
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => 'p2']);
// 提交事務
Db::commit();
}
測試結果:test1表新增了第二次事務操作的數據,但記錄的主鍵標識爲2。
測試結論:在代碼中啓用事務執行sql操作後,即使執行了rollback,但數據表中已進行過相關的預處理(如,標識主鍵自增),然後再回滾(撤銷)相關記錄。
3. 兩個併發事務的測試,分別執行兩個方法同時對 test1 和 test2 進行新增記錄操作(兩個瀏覽分別調用兩個測試方法)。
測試代碼:(注意先重建數據表)
/*
* 數據庫事務測試
*/
public function transactionTest1() {
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => 'fun1']);
// 休眠5s,製造時間差
sleep(5);
// 新增記錄
Db::table('test2')->insert(['content' => 'fun1']);
// 回滾事務
Db::rollback();
}
/*
* 數據庫事務測試
*/
public function transactionTest2() {
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => 'fun2']);
// 新增記錄
Db::table('test2')->insert(['content' => 'fun2']);
// 提交事務
Db::commit();
}
測試結果:test1 表中第二個方法新增的記錄主鍵標識爲2,test2 表中第二個方法新增的記錄主鍵爲1。
test1:
test2:
測試結論:併發事務中的sql操作會按調用順序執行。
4. 分別執行兩個方法,方法1啓用事務操作對test1進行新增記錄,查詢並輸出test1表的記錄,然後等待5秒進行rollback;在方法1休眠後用另外的瀏覽器調用方法2,查詢並輸出test1表的記錄。
測試代碼:(注意先重建數據表)
/*
* 數據庫事務測試
*/
public function transactionTest1() {
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => 'fun1']);
// 查詢數據
$data = Db::table('test1')->find();
dump($data);
// 休眠5s,製造時間差
sleep(5);
// 回滾事務
Db::rollback();
}
/*
* 數據庫事務測試
*/
public function transactionTest2() {
// 查詢數據
$data = Db::table('test1')->find();
dump($data);
}
測試結果:test1 表中第二個方法新增的記錄主鍵標識爲2,test2 表中第二個方法新增的記錄主鍵爲1。
方法1輸出:
方法2輸出:
test1:
測試結論:當前用戶可以查詢自己調用的事務操作中執行sql的結果,而其它用戶不能查詢到。
5. 在test1表增加觸發器,在test1表新增記錄前(後)同時在test2表新增記錄,測試啓用事務在test1執行新增記錄sql後再rollback是否會觸發觸發器操作。
測試代碼:(注意先重建數據表)
/* 創建觸發器 */
CREATE TRIGGER `insert` BEFORE INSERT ON `test1` FOR EACH ROW INSERT INTO test2 (content) VALUES (new.content)
;;
delimiter ;
/*
* 數據庫事務測試
*/
public function transactionTest1() {
// 啓用事務
Db::startTrans();
// 新增記錄
Db::table('test1')->insert(['content' => 'p1']);
// 回滾事務
Db::rollback();
// test2新增記錄
Db::table('test2')->insert(['content' => 'p2']);
}
測試結果:test1表中都沒有數據,而test2表中的新增記錄主鍵爲2。
test1:
test2:
測試結論:事務操作中執行的sql照樣觸發的觸發器,也會一併回滾撤銷操作。