2017-09-10 21 views
3

여러 서버에서 실행되지만 금융 거래를 위해 단일 데이터베이스를 공유하는 웹 응용 프로그램을 작성하려고합니다.DBI를 닫으면 postgres 데이터베이스에서 릴리스 잠금이 처리됩니까

간단히 말하면 계정 A에서 B로 금액을 이체하려고합니다.하지만 동일한 계좌에서 송금 요청이 여러 번있을 수 있습니다.

잔액이 절대 음수가 될 수 없으므로 SELECT FOR UPDATE를 사용하여 잔액을 가져 와서 행을 잠그기로했습니다.

나는 데이터베이스에 연결 JDBI을 사용하고 있습니다 : http://jdbi.org/

코드 흐름은 다음과 같다 :

컨트롤러 : 여기

DBI dbi = new DBI(datasource); 

..... 
getAccountBalance(); 

.... 

transfer() 

는 DOA 부분

public int getAccountBalance(String id) { 
     Handle h = dbi.open(); 
     try{ 
      return h.createQuery("SELECT balance FROM accounts " + 
           " WHERE id=:id FOR UPDATE;") 
        .bind("id", id) 
        .mapTo(Integer.class) 
        .first(); 
     } finally { 
      h.close(); 
     } 
    } 
입니다

DAO가 잔액을 반환하며 잔액 확인을 s 전송이 가능하면 다른 전송 방법을 호출하여 전송할 수 있습니다. 내가 그것을 선택한 행에 대한 잠금을 해제합니다 getAccountBalance()에 핸들을 닫으면

public void transfer(String fromAccountId, String toAccountId, int transferAmount) { 
     Handle h = dbi.open(); 
     try{ 
      h.begin(); 
      h.createStatement("UPDATE accounts SET balance = balance - :transferAmount WHERE id = :fromAccountId") 
       .bind("fromAccountId", fromAccountId) 
       .bind("transferAmount", transferAmount) 
       .execute(); 
      h.createStatement("UPDATE accounts SET balance = balance + :transferAmount WHERE id = :toAccountId") 
       .bind("toAccountId", toAccountId) 
       .bind("transferAmount", transferAmount) 
       .execute(); 
      h.commit(); 
     } finally { 
      h.close(); 
     } 
    } 

내 질문은? 그렇다면 자물쇠를 어떻게 잡을 수 있습니까? 나는 DBI를 처음 사용합니다. 감사합니다.

답변

3

h.close() 전에 실제로 출시되었습니다. h.commit()입니다. 행 잠금은? L 트를 초과하여 보유되지 않습니다.

커밋 이전에 보유 된 잠금이 필요하다면 자문 잠금을 사용할 수는 있지만 약간 어색하며, 이와 같은 것을 권장하지는 않습니다.

그렇지 않으면 pessimistic vs optimistic locking을 읽으십시오. Optimistic vs. Pessimistic locking을 참조하십시오.

+0

메서드 A에서 잠금을 만들지 만 메서드 B에서 커밋합니다. 여전히 잠금을 유지합니까? 미안하지만 내가 일찍 제대로 설명하지 않았다면. –

+0

@AmitVig 당신의'dbi' 객체가 무엇인지, 또는'open' 메소드가 무엇인지 모르겠다. 그래서 대답하기가 어렵다. 요점은 * 그것을 획득 한 트랜잭션이 커밋 할 때까지 잠금이 유지된다는 것입니다. 첫 번째 메소드가 여전히 잠금을 유지하고 두 번째 메소드가 별도의 DBI 연결 내에서 호출되면 첫 번째 트랜잭션의 잠금이 무기한으로 차단됩니다. 또는 동일한 연결에서 동일한 열린 트랜잭션 내에서 호출하는 경우 이미 열려있는 트랜잭션에 대한 경고를 표시하지만 그렇지 않으면 잘 작동합니다. –

+0

그래서 야생 *에서 getAccountBalance는 명시 적 트랜잭션을 시작하지 않으므로 자동 커밋됩니다. 따라서 잠금 장치는 명령문이 반환되지 않은 상태로 유지되지 않습니다. 그러나 그것은 당신의 거래 경계가 무엇인지에 대해 몇 가지 추측을하고 있습니다. –