搜尋
首頁後端開發PHP問題PHP中如何使用PDO操作事務

本篇文章要為大家介紹PHP中使用PDO操作事務的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

PHP中如何使用PDO操作事務

關於交易的問題,我們就不多解釋了,以後在學習 MySQL 的相關內容時再深入的了解。今天我們主要是對 PDO 中操作事務的一些小測試,或許能發現一些比較好玩的內容。

在 MyISAM 上使用交易會怎麼樣?

首先,相信只要是學過一點點的 MySQL 相關知識的人都知道,在 MySQL 中常用的兩種表格類型就是 InnoDB 和 MyISAM 這兩種類型。當然,我們今天也不講它們全部的區別,但有一個區別是最明顯的,那就是 MyISAM 不支援事務。那麼,如果我們在 PDO 操作中對 MyISAM 進行事務操作會怎麼樣呢?

// myisam
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_myisam (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_myisam2 (name, age) values ('Joe', 12, 33)");

    // sleep(30);
    $pdo->commit();

} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

tran_myisam 和 tran_myisam2 表都是 MyISAM 類型的表,在這段程式碼中,我們故意寫錯了 tran_myisam2 的插入語句,讓它走到 catch 中。實際執行的結果是,報錯資訊正常輸出,tran_myisam 表的資料也被插入了。也就是說,針對 MyISAM 表的事務操作是沒有效果的。當然,PDO 也不會主動報錯,如果我們讓第二個 SQL 語句也是正常語句的話,PDO 只會正常執行結束,不會有任何的錯誤或提示訊息。

// innodb
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12, 3)");
    // sleep(30);
    $pdo->commit();

} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

我們可以開啟 sleep(30); 這行程式碼的註釋,也就是在交易提交前暫停 30 秒,然後在 MySQL 中查看 infomation_schema.INNODB_TRX 表。這個表中顯示的就是正在執行中的事務。在 InnoDB 類型的資料表執行時就可以看到一則交易正在執行的記錄,而 MyISAM 類型的表中則不會看到任何資訊。

不提交不回滾交易會發生什麼事?

假設我們忘了 commit() ,同時也沒有報錯,這條語句會執行成功嗎?就像下面這段程式碼一樣。

try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)");

    // 忘记写 $pdo->commit(); 了
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

PHP 會在腳本執行結束後,其實也就是在 $pdo 物件析構時回滾這個交易。也就是說,這裡的 SQL 語句是不會執行的。但是,盡量不要這麼做,因為在正式環境中,我們的程式碼非常複雜,而且不一定會析構成功。這樣的話,可能會有長時間佔據的事務存在,最終結果就是會導致 MySQL 的 IPQS 奇高,而且還很難找到原因。所以,在使用事務的時候,一定要記得 commit() 和 rollBack() 都是我們的親兄弟,絕對不能落下他們。

上一個交易沒有提交沒有回滾,下一個交易會執行嗎?

同樣的,在上一個問題的基礎上我們再繼續延伸。如果有兩個事務依序執行,第一個事務沒有提交,沒有回滾,那麼下一個事務還能執行嗎?

// innodb
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)");
    // 忘记写 $pdo->commit(); 了
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL;
}

// innodb
try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->beginTransaction();
    $pdo->exec("insert into tran_innodb (name, age) values ('BW', 12)");
    $pdo->exec("insert into tran_innodb2 (name, age) values ('BW', 12)");

    // sleep(30);
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "Failed: " . $e->getMessage(), PHP_EOL; // Failed: There is already an active transaction
}

我們可以看到,第二段事務直接就報錯了,內容是:「這裡有一個已經存在的活動事務」。也就是說如果上一個交易沒有提交沒有回滾的話,第二個交易是無法執行的。

總結

今天我們只是學習並測試了幾個事務相關的小問題,但問題雖小卻有可能帶來嚴重的線上事故,大家在開發的時候一定要小心。關於事務的詳細內容在未來深入學習 MySQL 的時候我們再好好研究。

測試程式碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP中使用PDO操作事务的一些小测试.php

推薦學習:php影片教學

#

以上是PHP中如何使用PDO操作事務的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:segmentfault。如有侵權,請聯絡admin@php.cn刪除
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

方法:1、用“str_replace(" ","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\&nbsp\;||\xc2\xa0)/","其他字符",$str)”语句。

php怎么查找字符串是第几位php怎么查找字符串是第几位Apr 22, 2022 pm 06:48 PM

查找方法:1、用strpos(),语法“strpos("字符串值","查找子串")+1”;2、用stripos(),语法“strpos("字符串值","查找子串")+1”。因为字符串是从0开始计数的,因此两个函数获取的位置需要进行加1处理。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用