2011-01-12 3 views
1

SELECT 및 가능한 INSERT 인 트랜잭션이 있습니다. 동시성을 이유로 SELECTFOR UPDATE을 추가했습니다. 유령 행을 방지하기 위해 나는 SERIALIZABLE 트랜잭션 격리 수준을 사용하고 있습니다. 이 테이블에 행이있을 때이 모든 작동합니다, 있지만 테이블이 비어 있지 않은 경우. 테이블이 비어있는 경우 SELECT FOR UPDATE은 (단독적인) 잠금을 수행하지 않으며 동시 스레드/프로세스는 잠겨 있지 않고 동일한 SELECT FOR UPDATE을 발행 할 수 있습니다.innodb 및 serializable 트랜잭션을 사용하는 Mysql은 항상 행을 잠그지 않습니다

CREATE TABLE t (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    display_order INT 
) ENGINE = InnoDB; 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
START TRANSACTION; 
SELECT COALESCE(MAX(display_order), 0) + 1 from t FOR UPDATE; 

.. 

이 개념은 SQL Server에서는 예상대로 작동하지만 MySQL에서는 예상대로 작동합니다. 내가 뭘 잘못하고 있는지에 대한 아이디어가 있습니까?

편집

display_order에 인덱스를 추가하면 동작을 변경하지 않습니다. http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html

당신이 저를 요구하는 경우에, mysql을가 구축되지 않은

이 내 권고가은 ... 그런 식으로 사용되는 :

답변

0

는이 문서에서 살펴 있었나요 당신은 그것을 affort 수 경우를 - > 테이블 전체를 잠급니다.

+0

더보기 5.1 문서, 격리 수준 관리가 지금은 전혀 다릅니다 – regilero

+0

MySQL의 문서는 명시 적으로 이러한 경우에 대한 이해를 사용하여 FOR UPDATE를 사용하는 것이 좋습니다. 빈 테이블과 의미가 다른 것처럼 보입니다. –

0

이것은 아마도 버그가 아닙니다.

서로 다른 데이터베이스가 특정 트랜잭션 격리 수준을 구현하는 방식은 100 % 일치하지 않으며, 다르게 행동하는 고려해야 할 많은 경우가 있습니다. InnoDB는 오라클을 모방하기위한 것이었지만, 심지어 거기에서, 나는 그것이 다르게 작동하는 경우가 있다고 믿습니다. 응용 프로그램이 특정 트랜잭션 격리 모드에서 매우 미묘한 잠금 동작에 의존하는 경우

, 그것은 아마 분류됩니다

  • 을하더라도 지금 당장 "작품"누군가가 데이터베이스 스키마를 변경하는 경우, 그것은 그렇지 않을 수도
+0

나는 이것이 반드시 버그는 아니라는 점에 동의한다, 나는 그것이 내가 그것을보고 싶어하는 방식으로 작동하지 않는 이유가 궁금 할 뿐이다. 나는이 문제에 관해서는 MySQL의 문서에서 아무것도 찾을 수 없었다. –

1

잠금의 미묘한 차이에 의존하는 경우, b는이 뭔가 재미에게있어 코드를 유지하는 엔지니어가 데이터베이스를 사용하고 방법을 이해하는 것 같지는 않다 oth 트랜잭션은 실제 잠금을 얻을 준비가되었습니다. 트랜잭션 중 하나가 삽입을 시도하자마자 잠금이있게됩니다. 두 트랜잭션 모두 시도하면 교착 상태이 발생하고 롤백됩니다. 둘 중 하나만 시도하면 잠금 대기 시간 초과 이 표시됩니다.

잠금 대기 시간 초과를 감지하면 롤백 할 수 있으며 다음 트랜잭션이 삽입을 수행 할 수 있습니다.

그래서 교착 상태 예외 또는 시간 초과 예외가 발생할 가능성이 매우 높습니다. 은 상황을 저장해야합니다.. 그러나 완벽한 '직렬화 가능'상황에 대해 말하면 이것은 실제로 빈 테이블의 나쁜 부작용입니다. 엔진은 모든 경우에 완벽 할 수는 없습니다. 최소한 이중 트랜잭션 삽입은 할 수 없습니다.

어제 엔진 seriability 대 진정한 seriability의 흥미로운 사례를 전송했습니다, potsgreSQl 문서에, 그것은 재미의 예를 확인 : http://www.postgresql.org/docs/8.4/static/transaction-iso.html#MVCC-SERIALIZABILITY

업데이트 : 다른 흥미로운 자원 :에서 Does MySQL/InnoDB implement true serializable isolation?

+0

교착 상태/시간 초과 가능성도 눈치 챘습니다. 교착 상태/시간 초과를 처리하고 트랜잭션을 다시 시도하는 것은 가능하지만 가능한 교착 상태가없는 깨끗한 솔루션을 선호합니다. –

+0

직렬화 가능 트랜잭션을 처리하는 경우 트랜잭션 처리 (재시도 루프 사용)에서 이미 예외를 처리해야합니다. 교착 상태 중단은 처리 할 또 다른 예외이며 응용 프로그램과 동일한 알고리즘입니다. Serializable 트랜잭션은 '분류 할 수없는 예외'를 얻을 가능성이 매우 높습니다. 동일한 방식으로 교착 상태를 감지했습니다. – regilero

+0

물론 이러한 예외를 처리하고 교착 상태/시간 초과 예외가 발생하면 트랜잭션을 다시 시도하지만 (독점적 인) 잠금이 취해지지 않는 이유가 궁금합니다 (가능한 교착 상태를 방지해야 함). –