MySQL 자동 증가 필드 자체적으로 재설정


12

자동 증가 필드가 INT (11)로 설정된 MySQL 테이블이 있습니다. 이 테이블은 애플리케이션에서 실행중인 작업 목록을 거의 저장합니다. 응용 프로그램 수명 동안 특정 시점에 테이블에는 수천 개의 항목이 포함되거나 완전히 비어있을 수 있습니다 (예 : 모든 것이 완료되었습니다).

이 필드는 다른 것에 외래 키가 없습니다.

자동 증가는 실제로 재설정을 트랩 할 수 없었지만 무작위로 스스로 0으로 재설정되는 것처럼 보입니다.

자동 증분 필드가 600,000 레코드 정도까지 올라가고 잠시 후 자동 증분 필드가 1000 년대 초에 실행되고있는 것으로 보이므로 문제가 분명해집니다.

테이블이 비어 있으면 자동 증분 자체가 재설정되는 것과 거의 같습니다.

이것이 가능하고 가능하다면 어떻게 끄거나 재설정 방식을 변경합니까?

그렇지 않은 경우, 왜이 작업을 수행하는지에 대한 설명이 있습니까?

감사!


어떤 버전의 MySQL입니까? 트랜잭션 또는 복제가 사용 중입니까?
thinice

답변:


26

자동 증분 카운터는 디스크가 아닌 주 메모리에만 저장됩니다.

http://dev.mysql.com/doc/refman/4.1/en/innodb-auto-increment-handling.html

이로 인해 서비스 (또는 서버)가 다시 시작되면 다음이 발생합니다.

서버 시작 후, 테이블 t에 첫 번째 삽입을 위해 InnoDB는 다음 명령문과 동등한 명령을 실행합니다. SELECT MAX (ai_col) FROM t FOR UPDATE;

InnoDB는 명령문에 의해 검색된 값을 1 씩 증가시키고이를 컬럼 및 테이블의 자동 증가 카운터에 지정합니다. 테이블이 비어 있으면 InnoDB는 값 1을 사용합니다.

따라서 일반 영어로 MySQL 서비스가 시작된 후에는 테이블의 자동 증가 값이 무엇인지 모릅니다. 따라서 처음 행을 삽입하면 자동 증가를 사용하는 필드의 최대 값을 찾고이 값에 1을 더한 다음 결과 값을 사용합니다. 행이 없으면 1에서 시작합니다.

사용자가 타사 결제 사이트로 리디렉션되는 다중 스레드 환경에서 테이블과 mysql의 자동 증가 기능을 사용하여 ID를 깔끔하게 관리 할 때 문제가되었습니다. 따라서 우리는 제 3자가 가져오고 우리에게 보낸 ID가 고유하고 그런 식으로 유지되도록해야했습니다 (물론 사용자가 리디렉션 된 후 거래를 취소 할 가능성이 있습니다).

따라서 행을 생성하고 생성 된 자동 증분 값을 가져 와서 테이블을 깨끗하게 유지하기 위해 행을 삭제하고 값을 지불 사이트로 전달했습니다. InnoDB가 AI 값을 처리하는 방식의 문제를 해결하기 위해 끝낸 것은 다음과 같습니다.

$query = "INSERT INTO transactions_counter () VALUES ();";
mysql_query($query);
$transactionId = mysql_insert_id();
$previousId = $transactionId - 1;
$query = "DELETE FROM transactions_counter WHERE transactionId='$previousId';";
mysql_query($query); 

이렇게하면 테이블을 불필요하게 폭파하지 않고 항상 테이블에 행으로 생성 된 최신 transactionId를 유지합니다.

희망이있는 다른 사람에게 도움이되기를 바랍니다.

편집 (2018-04-18) :

아래에 언급 된 Finesse는 MySQL 8.0 이상 에서이 동작이 수정 된 것으로 보입니다.

https://dev.mysql.com/worklog/task/?id=6204

해당 작업 로그의 문구에는 문제가 없지만 최신 버전의 InnoDB는 이제 재부팅시 지속적인 autoinc 값을 지원합니다.

-그레미오


첫 번째 게시물에 나쁘지 않습니다. +1.
ceejayoz 2016

Gremio에 대한 약간의 지식이 있습니다. 감사!! 나는 이것을 완전히 끝내고 나중에 검토 할 무언가로 내부적으로 문제를 보관했지만 다시 돌아 오면 솔루션이 매력적입니다!
Hooligancat

3

이 문제가 발생하여 빈 테이블에서 테이블 최적화를 실행할 때 자동 증가 값도 재설정되었습니다. 이 MySQL 버그 리포트를 참조하십시오 .

해결 방법으로 다음을 수행 할 수 있습니다.

ALTER TABLE a AUTO_INCREMENT=3 ENGINE=innoDB;

대신에 OPTIMIZE TABLE.

이것은 MySQL이 내부적으로하는 것 같습니다 (분명히 자동 증가 값을 설정하지 않고)


2

응용 프로그램 TRUNCATE TABLE에서 테이블을 비우기 위해 테이블을 비우는 경우 자동 증가 필드가 재설정됩니다. 다음은 질문에 대한 간단한 설명 입니다. 이 링크는 InnoDB가 trunc에서 auto_increments를 재설정하지 않는다고 언급했지만 버그 로보고되어 몇 년 전에 수정되었습니다.

내 추측이 맞다고 가정하면 문제를 해결하기 위해 잘림에서 삭제로 변경할 수 있습니다.


TRUNCATE를 사용하고 있다고 생각하지 않았지만 확인해야했습니다. 심지어 PHP 드라이버 수준까지 확인하기 위해 갔다. 그러나 우리는 아니었다. 그래도 가능한 해결책에 감사하십시오.
Hooligancat

1

해당 값의 명시 적 재설정, 해당 필드의 삭제 / 재 작성 또는 기타 유사한 폭력적인 작업 만 auto_increment 카운터를 재설정해야합니다. TRUNCATE는 정말 좋은 이론이었습니다. 마지막으로 목격 한 값이 600k 일 때 32 비트 INT를 갑자기 래핑하는 것은 불가능한 것 같습니다. 테이블이 비었기 때문에 재설정해서는 안됩니다. mysql 버그 또는 PHP 코드에 문제가 있습니다. 아니면 옆집 칸막이에있는 사람이 당신을 속이고 있습니다.

바이너리 로그 를 켜서 디버깅 할 수 있습니다.

SET INSERT_ID=3747670/*!*/;

그런 다음 적어도 카운터 재설정 직전을 포함하여 해당 테이블에서 발생하는 모든 세부 사항을 볼 수 있습니다.


디버그 팁에 감사드립니다. Serverfault를 체크인해야했기 때문에 오랜 시간이 걸렸습니다. 귀하의 팁에 감사드립니다
Hooligancat

0

ALTER TABLE table_name ENGINE = MyISAM

나를 위해 일합니다. 우리 테이블은 항상 매우 작게 유지되므로 InnoDB가 필요하지 않습니다.


거래가 필요하십니까?
Anthony Rutledge 6

0

InnoDB는 디스크에 자동 증분 값을 저장하지 않으므로 MySQL 서버가 종료되면 잊어 버립니다. MySQL이 다시 시작되면 InnoDB 엔진은 다음과 같이 자동 증분 값을 복원합니다 SELECT (MAX(id) + 1) AS auto_increment FROM table. 이것은 MySQL 버전 8.0에서 수정 된 버그 입니다 .

테이블 엔진을 변경하여 문제점을 해결하십시오.

ALTER TABLE table ENGINE = MyISAM

또는 릴리스 될 때 MySQL 서버를 버전 8.0으로 업데이트하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.