2013-05-02 2 views
0

저는 작업중인 웹 사이트에서 PayPal Payments Standard를 구현하고 있습니다. 질문은 PayPal과 관련이 없습니다. 나는이 문제를 실제 문제를 통해 전달하고자합니다.MySQL 트랜잭션 : 쓰는 동안 읽음

페이팔은 두 가지 방법으로 지불에 대한 서버를 알릴 수 있습니다 :

  1. 페이팔 IPN - 각 결제 후 페이팔 트랜잭션이있는 URL (당신에 의해 선택)에 (서버 간) 알림을 보냅니다 세부.
  2. PayPal PDT - 결제 후 (PP 계정에서 설정 한 경우) PayPal은 사용자를 귀하의 사이트로 리디렉션하여 URL에 거래 ID를 전달하므로 해당 거래에 대한 PayPal에 문의하여 세부 정보를 얻을 수 있습니다 .

문제는 당신이 어느 쪽이 먼저 발생 확신 할 수있다 :

  • 이 서버가 IPN 통지 것
  • 는 사용자가 사이트에 다시 연결됩니다

먼저 트랜잭션이 두 번 처리되고 있지 않은지 확인하고 싶습니다. 그래서 두 경우 모두 페이팔 (그리고 지불 상태가 실제로는 문제가되지 않지만 현재)에서 오는 트랜잭션 ID에 대해 내 DB에 쿼리를 보내서 해당 트랜잭션을 저장하고 처리했는지 확인합니다. 그렇지 않은 경우 처리하고 다른 트랜잭션 세부 정보가있는 트랜잭션 ID를 내 데이터베이스에 저장합니다.

내가 첫 번째 요청 처리를 시작하면 어떻게됩니까 질문

은 (는 PDT..so 사용자가 다시 내 사이트로 이동했지만, 내 서버가 아직 IPN 통지하지 않은하자) 하지만 실제로 데이터베이스에 트랜잭션을 저장하기 전에 두 번째 (IPN) 요청이 도착하고 DB에서 트랜잭션을 찾지 못하기 때문에 트랜잭션을 처리하려고 시도합니다.

데이터베이스에 트랜잭션을 쓰는 동안 다른 트랜잭션 쿼리를 사용하여 해당 트랜잭션 ID를 찾을 수 없습니다.

필자는 InnoDB를 사용하고 있으며, 쓰기 시간 동안 전체 테이블을 잠그고 싶지 않습니다. 트랜잭션으로 간단히 해결할 수 있습니까? 해당 행을 "수동으로"잠글 수 있습니까? 나는 정말로 혼란 스럽다. 경험이 풍부한 몇몇의 MySQL 개발자들이 나에게이 점을 분명히하고 문제를 해결하는 데 도움이되기를 바란다.

답변

1

웹 컨텍스트에서 네이티브 데이터베이스 잠금이 거의 사용되지 않습니다 (특히 이와 같은 상황에서). MySQL 연결은 일반적으로 영구적 인 방식으로 수행되지 않습니다. 스크립트가 종료되면 MySQL 연결과 모든 잠금이 해제되고 진행중인 트랜잭션은 롤백됩니다.

상황 1 : 그들은 페이팔을 머리 경우, 구매

을 종료 할 HTTP 리디렉션을 통해 전송하고 종료 스크립트를 완료하기 위해 페이팔의 사이트에 사용자를 직접. 잠금/트랜잭션은 릴리스/롤백되며 DB와 관련하여 "처녀"상태로 돌아옵니다. 그들의 기록은 더 이상 잠겨 있지 않습니다.

상황 2 : Paypal은 서버 대 서버 응답을 수행합니다.이 작업은 사용자가 서버에 설정 한 연결과 완전히 다른 별도의 HTTP 연결을 통해 수행됩니다. 즉, 귀하가 서버에 설정 한 모든 잠금 장치가 < -> 사용자 연결은 페이팔 < -> yourserver 세션과 구별되며 페이팔 응답은 잠긴 테이블을 만날 것입니다. 물론 페이팔 응답이 언제 나타날지 예측할 방법이 없습니다. 네트워크 신이 당신에게 미소를 짓고 페이팔 (paypal)이 늪에 빠지지 않으면 사용자가 매우 빨리 응답하고 사용자가 연결되어있는 동안 응답을받을 수 있습니다. 작업이 느리고 응답이 지연되는 경우 MAY 사용자가 < -> 서버 세션을 완료했기 때문에 잠금 해제 된 테이블/행이 발생합니다.

너 은 영구적 인 MySQL 연결을 사용하지만 완전히 다른 고통의 세계를 열어줍니다. 예 : 스크립트가 처리 중반에 트리거되는 버그가있는 경우를 생각해보십시오. 연결, 트랜잭션 작업, 잠금 설정 ... 그리고 나서 스크립트는 죽습니다. MySQL 커넥션은 영속적이기 때문에, MySQL은 클라이언트 스크립트가 죽었다는 사실을 알지 못할 것이고, 트랜잭션/락을 진행 중에 유지할 것이다. 그러나 연결은 여전히 ​​거기에 앉아 있고 다른 세션이 연결을 기다리는 공유 풀에 있습니다. 언제나 새로운 스크립트는 오래된 "오래된"연결을 가지고 있다는 것을 전혀 모릅니다. 그것은 자물쇠와 거래의 혼란의 한가운데로 나아갈 것입니다. 버그 스 크립트는 시스템 전체에 쓰레기를 버리고 다른 스크립트는 그 쓰레기에 대처할 수 없기 때문에 쉽게 이런 교착 상태에 처할 수 있습니다.

기본적으로 시스템 상단에 자체 잠금 메커니즘을 구현하지 않는 한. UPDATE users SET locked=1 WHERE id=XXX을 사용하면 스크립트 당 1- 샷 컨텍스트를 제외하고 웹 컨텍스트에서 원시 DB 잠금 메커니즘을 사용할 수 없습니다. 여러 개의 독립적 인 요청에 대해 잠금을 시도해서는 안됩니다.