2014-10-30 16 views
0

나는 여전히 테이블 행 잠금에 대해 혼란스러워합니다. 저는 MySQL/PHP를 사용하고 있습니다. 여기에 제 시나리오가 있습니다.행 레벨 잠금 - MySQL - 업데이트 용

내 응용 프로그램에서 요청 및 게시물을 추적하는 데 사용하는 테이블 집합이 있습니다. 사용자는 항목 (테이블 ITEM (I))에 대한 전기 (테이블 POSTING (P))를 생성하고 개별 사용자 (테이블 REQUEST (R))에 요청을 발송하거나 게시하고 게시물 응답))이 사용자 게시 항목에서 허용됩니다.

예 : 저는 자전거를 소유 한 사용자입니다. 나는 그것을 게시하고 개별 사용자에게 요청을 보냅니다. 나로부터 요청을받는 사용자는 수락/거절/또는 아무 것도 할 수 없습니다. 그들이 수락하면 - 예약되어 있습니다. 다른 사용자는 내 게시물을 찾고 항목에 '적용'할 수 있습니다. 나는 그들의 요구를 '받아들이거나'무시할 수있는 능력이있다. 동의하면 항목이 예약됩니다.

내가 누군가가 요청을 허락하고 싶지 : ITEM (I)에서

  1. 잠금 행을 항목에 게시 (P)의

  2. 잠금 행을 해당 테이블을 테이블 (행이있는 경우) 항목

  3. 로크 행에 대해 전송 된 요청에 대한 요청의 항목

  4. 로크 행을 대응하는 (R) 테이블 (들) POSTING_RESPONSE (PR) 테이블 (행이 존재하는 경우) 어떤 POSTING_RESPONSE에/모든

  5. 갱신 '없음'으로

  6. 업데이트 게시 상태 '예약'에 항목

  7. 업데이트 항목 상태를 대응에 모든 요청이 수락 한 외에 '거부'하는

  8. 갱신 '거부'- 업데이 트를 하나

'허용'에3210

이 예제에서는 상태 중복을 무시하십시오.

이제 AUTOCOMMIT을 false로 남겨두고 # 1-4가 "select ... for update"와 함께 수행 될 수 있다고 가정했습니다. 업데이트 여부에 관계없이 이러한 선택 진술로 저지 할 수 있습니다. 그렇다면 업데이트를 계속할 수 있습니다. 그런 다음 업데이트 # 5 ~ 8을 완료 한 후 커밋하고 행을 잠금 해제합니다.

나는이 문제를 해결하는 데 어려움을 겪고 있으며, 내가하고있는 일이나 내 생각이 올바르지 않기 때문에 문제인지 알 수 없습니다.

한 가지 더 ... 항목의 상태를 EXPIRED (취소됨) 또는 CANCELLED (취소됨)로 업데이트 할 수있는 다른 프로세스가 있습니다. 내 접근 방식의 유일한 해결책은 UPDATE 문 내에서 WHERE 절에 가능한 모든 조건을 넣는 것이 아니라는 점입니다.이 방법은 쉽게 유지 보수 할 수 없습니다.

+1

일반적으로 SELECT는 비 잠금 식으로 읽습니다. SELECT를 잠 그려면 [잠금 읽기] (http://dev.mysql.com/doc/refman/5.6/en/innodb-locking-reads.html)를 지정해야합니다. –

+0

@JayBlanchard, 설명해 주시겠습니까? 어쩌면 나는 단지 두껍다.하지만 내가 모인 것에서 당신의 심판을 살펴봤을 때, 두 가지 옵션 만있다 : LOCK IN SHARE MODE - 읽기를 막지 않을 것이다 - 그리고 FOR UPDATE - 위의 예에서 보는 바와 같다. . 위의 예에서 FOR UPDATE가 작동하지 않습니까? 그렇지 않다면, 무엇을해야합니까 ?? – NEW2WEB

+0

아니요, 방금 읽지 않으 셨습니다. 당신에게 효과가없는 것은 무엇입니까? –

답변

0

미니 거래 : 하나의 검색어로 처리합니다.

UPDATE item 
LEFT JOIN posting 
    ON posting.item_id = item.id -- or however 
LEFT JOIN request 
    ON request.item_id = item.id -- or however 
LEFT JOIN posting_reponse 
    ON posting_response.item_id = item.id 
SET 
    item.status = 'Reserved', 
    posting.status = 'Unavailable', 
    posting_reponse.status = 'Rejected', 
    request.status = IF(request.id = some-current-id,'Accepted','Rejected') 
WHERE item.id = some-id AND item.status='Available'; 

...정말로은 원하지 않습니다 : P

+0

Wrikken - 이것은 아마도 갈 길입니다. 그러나 나는 여전히 읽음을 위해 잠그는 것에있어 잘못된 점을 얻지 못합니까? – NEW2WEB

+0

'다른 프로세스가이 데이터를 읽을 수 없습니다'라고 말하면이 데이터를 무시하지 않지만 데이터를 사용할 수있을 때까지 프로세스가 중지됩니다. 매우 소통량이 적은 프로젝트에서는 제대로 작동하지만 소수의 방문자를 넘어서 확장되지는 않습니다. 적당히 활성 인 프로젝트는 모든 종류의 (하위) 프로세스/다른 사람들을 기다리는 요청으로 인해 중단 될 것입니다. 요청이 트래픽이 증가함에 따라 점점 더 많은 시간이 소요되고 잠금 시간 초과 오류가 발생하는 지점에 도달하게됩니다. 시간 제한을 늘릴 수는 있지만 아무 일도 일어나지 않을 때까지 1 분 이상 기다려야하는 경우 아무도 프로젝트를 더 이상 사용하지 않습니다. – Wrikken