1. 오류: "트랜잭션 내에서 PDO 인스턴스를 교환할 수 없습니다."
Laravel 소스 코드를 쿼리하면 setPdo 메서드에서 예외가 발생했음을 확인할 수 있습니다.
<?php public function setPdo($pdo) { if ($this->transactions >= 1) { throw new RuntimeException(" Can't swap PDO instance while within transaction. "); } $this->pdo = $pdo; return $this; } ?>
말 그대로 이해하면 이 오류는 트랜잭션이 활성화된 동안 데이터베이스 연결이 전환되기 때문에 발생합니다. 그러나 코드에서 데이터베이스 연결을 명시적으로 전환하지 않은 경우에도 이 오류가 발생할 수 있습니다. 예를 들어, 쿼리문 실행 시 오류가 발생하면 시스템은 연결이 끊어져서 문제가 발생했는지 확인하기 위해 tryAgainIfCausedByLostConnection 메서드를 사용합니다. 그렇다면 시스템은 다시 연결 메서드를 통해 다시 연결합니다. setPdo 메소드가 호출되는 연결 끊기 메소드를 통해 일부 작업을 수행합니다.
원인과 결과를 정리하고 나면 자연스럽게 문제 해결 방법을 알게 됩니다. 네트워크 상황을 확인하고 데이터베이스 연결이 끊어진 이유를 확인하세요. 또는 시간 초과 설정이 잘못되었을 수 있습니다. 상대적으로 더러운 해결책은 쿼리하기 전에 DB::reconnect() 메서드를 실행하여 데이터베이스에 다시 연결하는 것입니다.
2. 오류: "작업을 삭제할 수 없습니다: NOT_FOUND"
이 문제는 실제로 Laravel과 관련이 없으며 대기열 서비스 Beanstalk로 인해 발생합니다.
이 문제를 해결하려면 먼저 메시지의 수명 주기를 이해해야 합니다. 즉, 메시지가 대기열에 들어가면 동시에 READY 상태가 됩니다. 시간은 이 메시지가 실행되도록 허용된 시간을 나타내는 TTR(실행 시간) 타이머와 연결됩니다. 이 메시지가 소비되면 예약됨 상태가 되며, 메시지는 삭제됩니다. 시간이 TTR보다 너무 길면 시스템은 소비자가 전화를 끊은 것으로 간주하고 RESERVED 상태에서 READY 상태로 메시지를 반환한 후 재처리를 위해 다른 소비자에게 전달합니다. 따라서 동일한 메시지가 여러 소비자에 의해 처리될 수 있습니다. 처리를 완료한 첫 번째 소비자는 메시지를 정상적으로 삭제할 수 있지만, 나머지 소비자는 메시지 삭제 시 삭제할 수 없는 오류를 보고하게 됩니다.
해결책은 매우 간단합니다. 첫째, TTR 설정이 너무 작지 않도록 해야 합니다. 둘째, Beanstalk는 실제로 너무 긴 실행 시간 문제를 해결하기 위해 특별한 터치 명령을 제공합니다. 또한 때로는 여러 소비자가 동일한 메시지를 동시에 처리하는 상황을 피하기 위해 애플리케이션 수준에서 잠금을 설정해야 할 수도 있습니다.
3. 오류: "모델에 대한 쿼리 결과가 없습니다."
Laravel 읽기-쓰기 분리가 활성화되면 소비자는 메시지를 처리할 때 유사한 오류를 받을 수 있습니다. 잠재적으로 문제가 있는 대기열 명령은 다음과 같습니다.
<?php class Foo extends Command implements SelfHandling, ShouldBeQueued { use InteractsWithQueue, SerializesModels; protected $bar; public function __construct($id) { $this->bar = Bar::find($id); } public function handle() { // $this->bar } } ?>
분명히 Laravel 읽기-쓰기 분리가 켜져 있으면 find는 마스터-슬레이브 지연으로 인해 해당 데이터를 쿼리하지 못할 수 있습니다. 이를 분석하면 아마도 다음과 같이 작성을 수정하게 될 것입니다.
<?php class Foo extends Command implements SelfHandling, ShouldBeQueued { use InteractsWithQueue, SerializesModels; protected $bar; public function __construct($id) { $this->bar = Bar::onWriteConnection()->find($id); } public function handle() { // $this->bar } } ?>
즉, 쿼리는 Laravel의 onWriteConnection 메소드를 통해 메인 서버에서 수정되지만 실제로는 유효하지 않습니다. 문제의 핵심은 역직렬화 중에 시스템이 서버에서 findOrFail을 한 번 호출한다는 것입니다.
<?php protected function getRestoredPropertyValue($value) { return $value instanceof ModelIdentifier ? (new $value->class)->findOrFail($value->id) : $value; } ?>
프레임워크를 해킹할 수 없기 때문에 onWriteConnection은 의미가 없습니다. 사실 다른 각도에서 문제를 보면, 직렬화할 때 데이터베이스 객체를 속성으로 사용하지 않도록 주의하세요:
<?php class Foo extends Command implements SelfHandling, ShouldBeQueued { use InteractsWithQueue, SerializesModels; protected $id; public function __construct($id) { $this->id = $id; } public function handle() { $bar = Bar::onWriteConnection()->find($this->id); } } ?>
4. 요약
위 내용은 제가 사용할 때 접한 내용입니다. Laravel 여러 가지 대표적인 오류 보고서 및 해결 방법에 대해 궁금한 점이 있으면 공유해 주세요. 이 글이 모든 분들의 공부나 업무에 조금이나마 도움이 되었으면 좋겠습니다.
Laravel의 일반적인 오류 및 해결 방법에 대한 더 많은 관련 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!