2013-05-23 3 views
2

AUTO_INCREMENT 값의 시퀀스에서 발생할 수있는 간격의 재사용과 관련하여 innodb의 정확한 동작을 이해하려고합니다. 문제는 문서에서 두 모순 된 설명을 발견 한 것 같습니다.잃어버린 AUTO_INCREMENT 값의 재사용

  1. http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-configurable.html 모든 잠금 모드에서

(0, 1, 2) 자동 증가 값을 생성 트랜잭션이 롤백 경우, 그 자동 증가 값이 "손실 ". 자동 증분 열의 값이 생성되면 은 "INSERT-like"문이 완료되었는지 여부와 포함 된 트랜잭션이 인지 여부와 포함 트랜잭션이 롤백되었는지 여부를 확인하기 위해 롤백 할 수 없습니다. 그러한 손실 된 값은 재사용되지 않습니다.

2. http://dev.mysql.com/doc/refman/5.6/en/innodb-restrictions.html

당신은 MySQL 서버를 다시 시작하면, InnoDB하지만 은 (AUTO_INCREMENT 컬럼에 대해 생성하지만 저장되지 않습니다 것을 오래된 값을 다시 사용할 수 있습니다 즉, 다시 압연 된 이전 트렌젝션 동안 만들어진 값).

이렇게 손실 된 값은 다시 사용됩니까? 그들은 참으로 MySQL 서버를 다시 시작한 후에 다시 사용됩니다 경우에, 어떻게 InnoDB하지만 UPDATE위한 t에서 문

SELECT MAX (ai_col)의 등가을 실행하여 새로운 AUTO_INCREMENT 값을 결정한다는 생각이 가능하다

? 서버가 더 이상 자동 증가 값 앞에 을 다시 시작하지 않는 한

답변

1

첫 번째 경우는 정상적인 동작입니다 당신이 무엇을 기대할.

두 번째 경우는 이상한 경우입니다.

쓰기를 위해 1024를 할당한다고 가정 해 보겠습니다. 그러나 MySQL이 중지되거나 충돌하기 때문에 쓰기 또는 트랜잭션이 완료되지 않습니다. 어떤 경우에는 1024의 사용이 기록되므로 1025가 다음에 할당됩니다. 그러나 1024의 할당이 시작의 경우 테이블에 으로 기록되지 않은 작은 창이 있습니다. 이것은 케이스 2를 설명합니다.

또한, InnoDB는 새로운 할당을 위해 실제로 MAX를 (MyISAM은하지 않습니다) 수행하지 않습니다. 그것은 동등하다.그것은 그러나

는 또한 dbe.se에이

업데이트.

질문의 첫 번째 링크 (http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-traditional.html)는 동작을 설명합니다. 링크가 소모 될 경우 아래 선정 따옴표 : 당신이 InnoDB의 테이블에 대한 AUTO_INCREMENT 컬럼을 지정하는 경우

은 InnoDB 데이터 사전 테이블 핸들은 특별한 카운터가 할당에 사용되는 자동 증가 카운터라고 포함 새로운 열의 값. 이 카운터는 디스크가 아닌 주 메모리에만 저장됩니다.

따라서 실제 테이블에서 숫자가 개별적으로 증가하는 것은 런타임에 발생합니다. 이것은 갭을 설명합니다 : 새로운 가치의 할당은 그것을 쓰는 것과 같지 않습니다.

이노가 AUTO_INCREMENT 컬럼라는 ai_col 포함하는 테이블 (T)에 대한 자동 증가 카운터를 초기화하기 위해 다음 알고리즘을 사용한다 : 테이블 t에 먼저 삽입 들어, 서버를 시작한 후을 이노이 동등한 실행 성명 :

따라서 성공적으로 할당되었지만 서버 재시작으로 인한 쓰기 실패는 폐기됩니다.

+0

네, 이상한 동작은 "InnoDB가 실제로 MAX를 수행하지 않는다는 것"으로 만 설명 할 수 있습니다. 그렇지 않으면 카운터가 절대로 이전 값으로 되돌릴 수 없게됩니다. 하지만 MySql이 카운터를 초기화하는 방법은 무엇입니까? –

+1

@AndreyKon : 시작시 초기화되는 별도의 카운터에 저장됩니다. http://docs.oracle.com/cd/E17952_01/refman-5.6-ko/innodb-auto-increment-traditional.html 자세한 내용은 – gbn

+0

+1입니다. 예 : "서버를 시작한 후 처음 삽입 할 때 InnoDB는 테이블 t에 다음 문을 실행한다. SELECT MAX (ai_col) FROM t FOR UPDATE; " – RandomSeed

0

나는 그 자동 증가 값이 을 "손실"되는 , 자동 증가 값을 생성 트랜잭션이 롤백 경우이

을 의미 믿는다 생성해야합니다.

내가이 동작하지만, 아래의 테스트를 확인하는 권위있는 참조를 찾을 수 없습니다가 동의 할 것 같다

bash > mysql test 

mysql > CREATE TABLE ai (id INT AUTO_INCREMENT PRIMARY KEY); 
mysql > BEGIN; 
mysql > INSERT INTO ai VALUES (NULL); 
mysql > ROLLBACK; 
mysql > BEGIN; 
mysql > INSERT INTO ai VALUES (NULL); 
mysql > COMMIT; 
mysql > SELECT * FROM ai; 
+----+ 
| id | 
+----+ 
| 2 | 
+----+ 
mysql > BEGIN; 
mysql > INSERT INTO ai VALUES (NULL); 
mysql > ROLLBACK; 
mysql > -- expecting auto-increment value "3" to be "consumed" 
mysql > quit; 

bash > service mysql restart 
bash > mysql test 

mysql > BEGIN; 
mysql > INSERT INTO ai VALUES (NULL); 
mysql > COMMIT; 
mysql > SELECT * FROM ai; 
+----+ 
| id | 
+----+ 
| 2 | 
| 3 | 
+----+ 
+0

그러나 설명서에 따르면 AUTO_INCREMENT 카운터는 메모리에만 저장되고 다시 시작될 때마다 다시 계산되므로 다시 시작하면 카운터에 영향을 줄 수 없습니다. "추가 자동 증가 값이 필요하기 전에 서버가 다시 시작되지 않으면 생성 될 "... –

+0

나는 모순을 보지 못합니다. 자동 증가 값이 메모리에만 저장되면 재시작시 "손실"값이 "복구"됩니다. 위 시나리오에서 a-i 값은 '1', '2'및 '3'이 소비되지만 (실제로는 '2'값만 사용됩니다.) 다시 시작할 때, MySQL은 실제로 사용중인 마지막 a-i 값이 '2'라고 재 계산하므로, 다음 삽입은 a-i 값 '3'을 사용할 수 있습니다. – RandomSeed

+0

값 3을 저장하지 않은 경우 값 3을 다시 얻는 것이 문제가되지 않습니다. 하지만 내 ID의 값을 1로 오름차순으로 나누는 것이 가능한지 묻습니다. 주변 사람들은 가능하다고 불평합니다! –