mysqlcheck가 테이블을 손상되지 않은 것으로 잘못 보고하는 원인은 무엇입니까?

mysqlcheck가 테이블을 손상되지 않은 것으로 잘못 보고하는 원인은 무엇입니까?

우리는 각각 약 50개의 테이블이 포함된 100개 이상의 데이터베이스(대부분 InnoDB 테이블)를 보유한 고객 중 한 명을 위해 MySQL 서버를 관리하고 있습니다. 서버가 터져서 범인을 찾으려고 합니다. 으로 다시 시작하면 innodb_force_recovery = 2연결할 수 있고 error.log에 오류가 표시되지 않습니다. 더 중요한 것은 mysqlcheck --all-databases모든 테이블에 대해 "Ok"를 보고한다는 것입니다. 하지만 을 제거하면 innodb_force_recovery서버가 다시 충돌하고 error.log에 스택 추적을 기록하며 으로만 중지할 수 있습니다 kill -9.

이러한 상황에서 문제가 되는 데이터베이스를 어떻게 찾아야 하며, mysqlcheck가 손상된 테이블을 놓치게 만드는 원인은 무엇입니까? 그냥 무시하고 덤프에서 모든 데이터베이스를 복원하라고 말하지 마세요. 이는 하나 또는 두 개의 데이터베이스에 허용될 수 있으며 블루 문에서 한 번만 발생하는 경우 동일한 서버에 두 번 이상 문제가 있었고 덤프에서 모든 것을 복원하려면 너무 많은 시간과 수동 작업이 필요합니다. 시간.

서버 버전은 5.5.46이며 innodb_file_per_table활성화되어 있습니다.

요청한 error.log 발췌( The tablespace free space info is corrupt특정 테이블에 없고 수정할 수 없는 오류가 있다는 의미입니까?):

180222 17:13:48 mysqld_safe Starting mysqld daemon with databases from /home/mysql
180222 17:13:48 [Warning] 'THREAD_CONCURRENCY' is deprecated and will be removed in a future release.
180222 17:13:48 [Note] /usr/libexec/mysqld (mysqld 5.5.46) starting as process 26242 ...
180222 17:13:48 [Note] Plugin 'FEDERATED' is disabled.
180222 17:13:48 InnoDB: The InnoDB memory heap is disabled
180222 17:13:48 InnoDB: Mutexes and rw_locks use InnoDB's own implementation
180222 17:13:48 InnoDB: Compressed tables use zlib 1.2.3
180222 17:13:48 InnoDB: Using Linux native AIO
180222 17:13:48 InnoDB: Initializing buffer pool, size = 128.0M
180222 17:13:49 InnoDB: Completed initialization of buffer pool
180222 17:13:49 InnoDB: highest supported file format is Barracuda.
180222 17:13:49  InnoDB: Waiting for the background threads to start
180222 17:13:50 InnoDB: 5.5.46 started; log sequence number 1632912830888
180222 17:13:50 [Note] Server hostname (bind-address): '0.0.0.0'; port: 3306
180222 17:13:50 [Note]   - '0.0.0.0' resolves to '0.0.0.0';
180222 17:13:50 [Note] Server socket created on IP: '0.0.0.0'.
180222 17:13:50 [Note] Event Scheduler: Loaded 0 events
180222 17:13:50 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.5.46'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server (GPL) by Remi
InnoDB: Dump of the tablespace extent descriptor:  len 40; hex 000000000000000200000000061600000000126e00000004ffffffffffffffffffffffffffffbfaa; asc                    n                    ;
InnoDB: Serious error! InnoDB is trying to free page 512
InnoDB: though it is already marked as free in the tablespace!
InnoDB: The tablespace free space info is corrupt.
InnoDB: You may need to dump your InnoDB tables and recreate the whole
InnoDB: database!
InnoDB: Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
180222 17:13:50  InnoDB: Assertion failure in thread 2499464080 in file fsp0fsp.c line 3309
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
16:13:50 UTC - mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

key_buffer_size=268435456
read_buffer_size=1048576
max_used_connections=0
max_threads=512
thread_count=0
connection_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 1314506 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0x0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 0 thread_stack 0x30000
/usr/libexec/mysqld(my_print_stacktrace+0x33)[0x842a1f3]
/usr/libexec/mysqld(handle_fatal_signal+0x42b)[0x82d9d3b]
[0x7bc420]
[0x7bc410]
/lib/libc.so.6(gsignal+0x50)[0x626b10]
/lib/libc.so.6(abort+0x101)[0x628421]
/usr/libexec/mysqld[0x85012e7]
/usr/libexec/mysqld[0x850147e]
/usr/libexec/mysqld[0x849c0b1]
/usr/libexec/mysqld[0x84a8a61]
/usr/libexec/mysqld[0x8561fef]
/usr/libexec/mysqld[0x85570a9]
/usr/libexec/mysqld[0x847b082]
/usr/libexec/mysqld[0x846bf04]
/usr/libexec/mysqld[0x846dad4]
/lib/libpthread.so.0[0x50d912]
/lib/libc.so.6(clone+0x5e)[0x6d347e]
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
180222 17:13:50 mysqld_safe Number of processes running now: 0
180222 17:13:50 mysqld_safe mysqld restarted

답변1

오류 메시지 자체는 테이블 데이터를 확인해도 문제가 해결되지 않는 이유를 알려줍니다. 페이지(아마도 테이블이나 인덱스에서)를 해제하려고 시도했습니다. 하지만 그 페이지는 이미 무료로 표시되어 있었습니다. 즉, 페이지가 다른 테이블이나 인덱스에 제공될 수 있다고 간주될 때 테이블이나 인덱스 중 하나가 페이지를 사용 중이었습니다. 그리고 InnoDB가 어떤 페이지가 실제로 무료인지 알지 못하면 나쁜 일이 발생할 수 있습니다.

모든 테이블/인덱스 데이터를 덤프하고 다시 로드한다는 것은 InnoDB가 사용 가능한 페이지 모음을 다시 빌드할 수 있는 기회를 제공한다는 의미입니다. 이상적으로는 새로운 데이터베이스에서 이 작업을 수행하는 것이 좋습니다. 왜? 글쎄, 단 하나의 단일 손상 오류가 있다고 가정해서는 안됩니다. 따라서 데이터를 새로 설치하도록 이동하는 경우 감지되지 않은 추가 손상 문제가 있는지 걱정할 필요가 없습니다.

답변2

제안한 대로 해당 덤프에서 덤프하고 복원하는 것이 결국 모든 데이터베이스를 복원하기 위해 선택한 방법이었습니다. 운 좋게도 innodb_force_recovery = 2모든 것을 오류 없이 덤프할 수 있어서 백업의 덤프를 사용할 필요가 없었습니다. 물론 오류의 실제 원인을 찾아내고 싶었지만 MySQL은 버그 보고서에서 "테이블스페이스 여유 공간 정보가 손상되었습니다"라고 언급한 것 외에는 아무런 도움도 제공하지 않습니다. 오류의 원인을 파악하고 제거하지 않으면 결국 오류가 다시 발생할 것으로 예상됩니다. 고객은 아마도 나보다 더 화를 낼 것입니다.

하드웨어 불량이 원인일 수도 있지만 시스템에 있는 모든 디스크의 SMART 데이터는 양호해 보이고 /var/log/messages충돌 당시에는 의심스러운 내용이 포함되어 있지 않습니다. 예상치 못한 정전이나 재부팅도 발생하지 않았습니다.

관련 정보