이 글에서는 PDO를 사용하여 PHP에서 트랜잭션을 운영하는 방법을 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
트랜잭션 문제에 대해서는 앞으로 MySQL 관련 내용을 공부할 때 더 자세히 설명하지 않겠습니다. 오늘 우리는 주로 PDO의 트랜잭션 운영에 대한 몇 가지 작은 테스트를 수행하고 있으며 흥미로운 내용을 찾을 수 있을 것입니다.
우선 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 비디오 튜토리얼
위 내용은 PDO를 사용하여 PHP에서 트랜잭션을 운영하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!