這篇文章主要介紹了PHP中如何使用PDO操作事務(wù),具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)建站主要從事成都網(wǎng)站制作、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)白山,10多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):028-86922220
首先,相信只要是學(xué)過(guò)一點(diǎn)點(diǎn)的 MySQL 相關(guān)知識(shí)的人都知道,在 MySQL 中常用的兩種表類(lèi)型就是 InnoDB 和 MyISAM 這兩種類(lèi)型。當(dāng)然,我們今天也不講它們?nèi)康膮^(qū)別,但有一個(gè)區(qū)別是最明顯的,那就是 MyISAM 不支持事務(wù)。那么,如果我們?cè)?PDO 操作中對(duì) MyISAM 進(jìn)行事務(wù)操作會(huì)怎么樣呢?
// 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 類(lèi)型的表,在這段代碼中,我們故意寫(xiě)錯(cuò)了 tran_myisam2 的插入語(yǔ)句,讓它走到 catch 中。實(shí)際執(zhí)行的結(jié)果是,報(bào)錯(cuò)信息正常輸出,tran_myisam 表的數(shù)據(jù)也被插入了。也就是說(shuō),針對(duì) MyISAM 表的事務(wù)操作是沒(méi)有效果的。當(dāng)然,PDO 也不會(huì)主動(dòng)報(bào)錯(cuò),如果我們讓第二條 SQL 語(yǔ)句也是正常語(yǔ)句的話(huà),PDO 只會(huì)正常執(zhí)行結(jié)束,不會(huì)有任何的錯(cuò)誤或者提示信息。
// 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; }
我們可以打開(kāi) sleep(30); 這行代碼的注釋?zhuān)簿褪窃谑聞?wù)提交前暫停 30 秒,然后在 MySQL 中查看 infomation_schema.INNODB_TRX 表。這個(gè)表中顯示的就是正在執(zhí)行中的事務(wù)。在 InnoDB 類(lèi)型的表執(zhí)行時(shí)就可以看到一條事務(wù)正在執(zhí)行的記錄,而 MyISAM 類(lèi)型的表中則不會(huì)看到任何信息。
假設(shè)我們忘寫(xiě)了 commit() ,同時(shí)也沒(méi)有報(bào)錯(cuò),這條語(yǔ)句會(huì)執(zhí)行成功嗎?就像下面這段代碼一樣。
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)"); // 忘記寫(xiě) $pdo->commit(); 了 } catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL; }
PHP 會(huì)在腳本執(zhí)行結(jié)束后,其實(shí)也就是在 $pdo 對(duì)象析構(gòu)時(shí)回滾這個(gè)事務(wù)。也就是說(shuō),這里的 SQL 語(yǔ)句是不會(huì)執(zhí)行的。但是,盡量不要這么做,因?yàn)樵谡江h(huán)境中,我們的代碼非常復(fù)雜,而且不一定會(huì)析構(gòu)成功。這樣的話(huà),可能會(huì)有長(zhǎng)時(shí)間占據(jù)的事務(wù)存在,最終結(jié)果就是會(huì)導(dǎo)致 MySQL 的 IPQS 奇高,而且還很難找到原因。所以,在使用事務(wù)的時(shí)候,一定要記得 commit() 和 rollBack() 都是我們的親兄弟,絕不能落下他們。
同樣的,在上一個(gè)問(wèn)題的基礎(chǔ)上我們?cè)倮^續(xù)延伸。如果有兩個(gè)事務(wù)依次執(zhí)行,第一個(gè)事務(wù)沒(méi)有提交,沒(méi)有回滾,那么下一個(gè)事務(wù)還能執(zhí)行嗎?
// 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)"); // 忘記寫(xiě) $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 }
我們可以看到,第二段事務(wù)直接就報(bào)錯(cuò)了,內(nèi)容是:“這里有一個(gè)已經(jīng)存在的活動(dòng)事務(wù)”。也就是說(shuō)如果上一個(gè)事務(wù)沒(méi)有提交沒(méi)有回滾的話(huà),第二個(gè)事務(wù)是無(wú)法執(zhí)行的。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“PHP中如何使用PDO操作事務(wù)”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!