MySQL에서 ibdata1 파일을 축소 / 제거하는 방법


561

localhost에서 MySQL을 R에서 통계를 수행하기위한 "쿼리 도구"로 사용하고 있습니다. 즉, R 스크립트를 실행할 때마다 새 데이터베이스 (A)를 만들고 새 테이블 (B)을 만들고 데이터를 B로 가져옵니다. , 필요한 것을 얻기 위해 쿼리를 제출 한 다음 B를 삭제하고 A를 삭제합니다.

그것은 잘 작동하지만 ibdata 파일 크기가 빠르게 증가하고 MySQL에 아무것도 저장하지 않았지만 ibdata1 파일이 이미 100MB를 초과했습니다.

설치에 기본 MySQL 설정을 사용하고 있습니다. 일정 시간이 지나면 ibdata1 파일을 자동으로 축소 / 지우는 방법이 있습니까?


답변:


777

즉, ibdata1축소되지는 MySQL을의 특히 짜증나는 기능입니다. ibdata1파일은 실제로 당신이 모든 데이터베이스를 삭제 파일을 제거하고 덤프를 다시로드하지 않는 한 축소 할 수 없습니다.

그러나 인덱스를 포함한 각 테이블이 별도의 파일로 저장되도록 MySQL을 구성 할 수 있습니다. 그렇게하면 ibdata1커지지 않을 것입니다. Bill Karwin의 의견 에 따르면 이것은 MySQL 5.6.6 버전에서 기본적으로 활성화되어 있습니다.

얼마 전에 나는 이것을했다. 그러나 각 테이블에 대해 별도의 파일을 사용하도록 서버를 설정 my.cnf하려면이를 활성화하기 위해 변경해야합니다 .

[mysqld]
innodb_file_per_table=1

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

공간을 확보 ibdata1하려면 실제로 파일을 삭제해야합니다.

  1. 수행합니다 mysqldump모든 데이터베이스, 프로 시저, 트리거 등의 제외 mysqlperformance_schema데이터베이스
  2. 위의 두 데이터베이스를 제외한 모든 데이터베이스를 삭제하십시오.
  3. MySQL을 중지
  4. 삭제 ibdata1ib_log파일
  5. mysql 시작
  6. 덤프에서 복원

5 단계에서 MySQL을 시작하면 ibdata1ib_log파일이 다시 생성됩니다.

이제 당신은 갈 수 있습니다. 분석 할 새 데이터베이스를 작성하면 테이블 ibd*이에있는 파일이 아닌 별도의 파일에 ibdata1있습니다. 보통 곧 데이터베이스를 ibd*삭제 하면 파일이 삭제됩니다.

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

아마 이것을 보았을 것입니다 :
http://bugs.mysql.com/bug.php?id=1341

명령을 사용 ALTER TABLE <tablename> ENGINE=innodb하거나 OPTIMIZE TABLE <tablename>ibdata1에서 데이터 및 색인 페이지를 추출하여 파일을 분리 할 수 ​​있습니다. 그러나 위의 단계를 수행하지 않으면 ibdata1이 축소되지 않습니다.

에 관해서는 information_schema, 그것은 떨어질 필요가 없습니다. 실제로는 테이블이 아니라 읽기 전용 뷰입니다. 그리고 데이터베이스 디렉토리조차도 그들과 관련된 파일이 없습니다. (가) informations_schema메모리 DB 엔진을 사용하고 떨어 정지에 재생됩니다 / mysqld에의 다시 시작합니다. https://dev.mysql.com/doc/refman/5.7/en/information-schema.html을 참조 하십시오 .


16
@JordanMagnuson information_schema를 삭제하지 않아도됩니다. 실제로는 테이블이 아니라 읽기 전용 뷰입니다. 그리고 그들과 관련된 파일이 없습니다. 데이터베이스를위한 디렉토리조차 없습니다. informations_schema는 메모리 db-engine을 사용하고 있으며 mysqld가 중지 / 다시 시작될 때 삭제 및 재생성됩니다. dev.mysql.com/doc/refman/5.5/en/information-schema.html을 참조하십시오 . performance_schema와 관련하여 나는 그 스키마를 직접 사용하지 않았습니다.
John P

4
이것이 최근의 것인지 모르겠지만 innodb_file_per_table 옵션이 활성화되면 "ALTER TABLE <tablename> ENGINE = InnoDB"(이미 InnoDB 인 경우에도)를 실행하면 테이블이 개별 파일로 이동합니다. . 데이터베이스 등을 삭제할 필요가 없습니다.
CR.

3
FWIW +1, MySQL 5.6은 innodb_file_per_table기본적으로 활성화 됩니다.
Bill Karwin 2016 년

3
예, ibdata1은 다른 파일과 함께 존재할 것으로 예상됩니다. ibdata1 파일은 여전히 ​​테이블, 실행 취소 로그 및 버퍼에 대한 메타 데이터를 보유합니다.
John P

1
ibdata1 파일로 인해 서버 공간이 부족하여 데이터베이스를 덤프 할 수도 없습니다. / var / lib / mysql ( "mysql", "ibdata1", "ib_logfile0"및 "ib_logfile1"제외)에서 파일을 이동 한 다음 단계를 수행하는 것이 동일합니까? 참조 stackoverflow.com/questions/2482491/...
Sophivorus

47

에 추가 존 P의 대답은 ,

Linux 시스템의 경우 다음 명령으로 1-6 단계를 수행 할 수 있습니다.

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. sudo /etc/init.d/mysqld stop
  4. sudo rm /var/lib/mysql/ibdata1
    sudo rm /var/lib/mysql/ib_logfile (명명 될 수있는 다른 ib_logfile 년대를 삭제 ib_logfile0, ib_logfile1등 ...)
  5. sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql

경고 :이 지침은이 mysql 인스턴스에 다른 데이터베이스가있는 경우 다른 데이터베이스를 잃을 수 있습니다. 보관하려는 모든 데이터베이스를 포함하도록 1, 2 및 6,7 단계를 수정하십시오.


6
InnoDB 테이블이있는 모든 데이터베이스에 대해 1, 2 및 6을 반복해야합니다.
Lorne의 후작

4
# 5와 # 6 사이에 몇 단계가 더 필요합니다. 데이터베이스를 다시 작성하고 권한을 다시 지정해야합니다. 그래서 프롬프트 MySQL의 클라이언트 명령에서 create database database_name;다음grant all privileges on database_name.* to 'username'@'localhost' identified by 'password';
프레드

1
@fred 나는 이것을 할 때 권한을 부여 할 필요가 없었습니다. 아마도 같은 이름으로 데이터베이스를 다시 작성했기 때문에?
crmpicco

2
Password:프롬프트 에서 암호를 입력하려면 (보다 안전한 방법 임) -p실제 암호없이 입력하십시오.
ADTC

mysqldump에 지시하지 않으면 트리거, 이벤트 및 루틴 / 함수는 덤프되지 않습니다. 데이터베이스에 포함 된 경우 --triggers, --events 및 --routines를 추가하십시오. 또한 --all-databases로 덤프하여 모든 데이터베이스를 하나씩 대신 덤프합니다.
Friek

34

innodb 테이블을 삭제하면 MySQL은 ibdata 파일 내부의 공간을 비우지 않으므로 계속 커집니다. 이 파일들은 거의 줄어들지 않습니다.

기존 ibdata 파일을 축소하는 방법 :

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

이를 스크립팅하고 일정 시간 후에 스크립트가 실행되도록 예약 할 수 있지만 위에서 설명한 설정의 경우 여러 테이블 스페이스가 더 쉬운 솔루션 인 것 같습니다.

구성 옵션을 사용하면 innodb_file_per_table여러 테이블 스페이스를 작성합니다. 즉, MySQL은 하나의 공유 파일 대신 각 테이블에 대해 별도의 파일을 만듭니다. 이러한 별도의 파일은 데이터베이스의 디렉토리에 저장되며이 데이터베이스를 삭제할 때 삭제됩니다. 이 경우 귀하의 경우 ibdata 파일을 축소 / 제거 할 필요가 없습니다.

다중 테이블 스페이스에 대한 추가 정보 :

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html


첫 번째 링크 깨진, 내가 찾을 수있는 가장 가까운 : dev.mysql.com/doc/refman/5.5/en/...
BlackICE에

14

MySQL 테이블 (일부)에 InnoDB 스토리지 엔진을 사용하는 경우 이미 기본 구성에 문제가있는 것 같습니다. MySQL의 데이터 디렉토리 (Debian / Ubuntu – / var / lib / mysql에 있음)에서 알 수 있듯이 'ibdata1'이라는 파일이 있습니다. MySQL 인스턴스의 거의 모든 InnoDB 데이터 (트랜잭션 로그가 아님)를 보유하며 상당히 커질 수 있습니다. 기본적으로이 파일의 초기 크기는 10Mb이며 자동으로 확장됩니다. 불행히도 InnoDB 데이터 파일은 의도적으로 축소 할 수 없습니다. 그렇기 때문에 DELETE, TRUNCATE, DROP 등이 파일에 사용 된 공간을 회수하지 않습니다.

좋은 설명과 해결책을 찾을 수 있다고 생각합니다.

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/


11

bash에서 허용 된 답변의 절차를 신속하게 스크립팅했습니다.

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

다른 이름으로 저장 purge_binlogs.sh하고 실행 하십시오 root.

제외 mysql, information_schema, performance_schema(및 binlog디렉토리).

관리자 자격 증명이 /root/.my.cnf있고 데이터베이스가 기본 /var/lib/mysql디렉토리 에 있다고 가정합니다 .

이 스크립트를 실행 한 후 이진 로그를 제거하여 다음과 같은 추가 디스크 공간을 확보 할 수도 있습니다.

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;

여전히 이유는 확실하지 않지만 오늘날 비슷한 프로세스 중에 일부 InnoDB 테이블이 손상되었으므로 alldatabases.sql모든 테이블이 정상인지 다시 확인하기 전에 제거하지 않을 것 입니다. 일부 개선 사항 : innodb_fast_shutdown=0종료 전 설정 , autocommit=0SQL 파일 가져 오기 전에 COMMIT설정 autocommit=1, SQL 파일 가져 오기 후 실행 및 설정 , mysqlcheck --all-databases백업 삭제 전에 사용하십시오 .
Victor

6

MySQL 여유 공간을 모니터링하는 것이 목표이고 MySQL이 ibdata 파일을 축소하는 것을 막을 수 없다면 테이블 상태 명령을 통해 가져 오십시오. 예:

MySQL> 5.1.24 :

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL <5.1.24 :

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

그런 다음이 값을 ibdata 파일과 비교하십시오.

du -b ibdata1

출처 : http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html


4

mysql-server 레시피의 새로운 버전에서는 위의 "mysql"데이터베이스가 손상 될 것이다. 이전 버전에서는 작동합니다. 새로운 일부 테이블에서는 INNODB 테이블 유형으로 전환되며 그렇게하면 테이블이 손상됩니다. 가장 쉬운 방법은 다음과 같습니다.

  • 모든 데이터베이스를 덤프
  • mysql-server를 제거하고
  • 남아있는 my.cnf에 추가하십시오 :
    [mysqld]
    innodb_file_per_table=1
  • / var / lib / mysql에서 모두 지우기
  • mysql-server를 설치하십시오
  • 사용자 및 데이터베이스 복원

1

이미 언급했듯이 ibdata1을 축소 할 수는 없지만 (덤핑하고 다시 빌드해야 함) 종종 실제 필요는 없습니다.

자동 확장 (아마도 가장 일반적인 크기 설정)을 사용하면 ibdata1이 스토리지를 미리 할당하여 거의 가득 찰 때마다 증가합니다. 공간이 이미 할당되어 있으므로 쓰기 속도가 더 빠릅니다.

데이터를 삭제하면 축소되지 않지만 파일 내부의 공간은 사용되지 않은 것으로 표시됩니다. 이제 새 데이터를 삽입하면 파일을 더 이상 늘리기 전에 파일의 빈 공간을 재사용합니다.

따라서 실제로 해당 데이터가 필요한 경우에만 계속 증가합니다. 실제로 다른 응용 프로그램을위한 공간이 필요하지 않으면 축소 할 이유가 없습니다.


66
나는 당신이 공간을 확보해야 할 필요성을 조금 무시하고 있다고 생각합니다.
drewish

2
60Gig 솔리드 스테이트 파티션이 있습니다. 4 + gig 데이터베이스로 작업하기 때문에 공간이 빨리 부족합니다. 나는 곧 mysql을 다른 파티션으로 옮기려고하지만이 질문과 답변은 그동안 저에게 도움이 될 것입니다
NullVoxPopuli

3
이 답변에 감사드립니다. 매우 도움이됩니다. 레거시 데이터에서 일부 테이블을 지 웠습니다. 디스크의 크기가 곧 다시 커지지 않는다는 것을 아는 것이 좋습니다.
브래드

1
500G ibdata1 파일이 있지만 그 안에 저장된 거의 모든 데이터가 이제 데이터베이스 별 파일에 저장됩니다. 이 엄청난 공간 낭비를 줄여야합니다!
frankster

2
말도 안돼! 최대 복부 팽만 유지하는 파일은 손질 할 필요 는 공간이 부족하고 있는지 여부 . 나는 그것을이라고 부를 것이다 storage leak.
ADTC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.