본문 바로가기

카테고리 없음

MySQL 5.5 Backup & Recovery Scenario v1.0

MySQL 5.5 Backup & Recovery Scenario v1.0

 

Date

Ver

Etc.

2011.05.11

1.0

 

 

 

 

 

 

 

 

 

1.    Backup & Recovery

DBMS Recovery 에 앞서 반드시 선행되어야 할 작업이 있다. 그것은 당연히도 Backup 이다. Backup 이 있어도 이를 제대로 사용하지 못해서는 Recovery 가 의미가 없다.

 

2.    Targets of Backup

A.     Database Engine

MySQL Engine 을 말한다. 초기 바이너리 로그파일을 압축 해제 후 Database 생성 스크립트를 돌리고 난 이후의 파일들을 말함이다. 데이터 파일은 다 분산 지정했음을 가정하고 이야기 하였다. 엔진은 크기가 1기가 미만으로 작다.

 

B.     my.cnf

MySQL Instance 에 대한 Configuration File 이다. kb 의 크기 정도밖에 하지 않지만 서버에 대한 셋팅값이 다 들어가 있는 파일로 유실되면 위험하다. 특히 InnoDB 의 경우 테이블 스페이스의 물리적 정보가 들어가 있어 더더욱 그러하다.

 

C.     binary log

binary log 에는 DB 의 변경내역이 들어간다. Oracle Redo Log / Archived Log 를 생각하면 된다. log-bin variable 을 활성화 해야 사용한다. 이 로그가 없는 경우 Crash 시점까지의 데이터 복구가 불가능해진다. ORACLE 로 보면 Restore 만 하고 Recover 를 하지 못한 경우와 동일하다.

 

D.     innodb datafile, innodb logfile, InnoDB Table frm

Storage Engine InnoDB Tablespace 를 사용한다. Tablespace 가 물리적으로 InnoDB Datafile 에 해당된다. 또 이 Storage Engine 이 사용하는 Redo Log File 이 있는데 이에 해당하는 것이 InnoDB Logfile 이다. 마지막으로 InnoDB 를 사용하는 Table 역시 Table 의 물리적 정보를 가지기 위해 {table_name}.frm 을 가진다.

 

E.     MyISAM Table, Index, frm

MyISAM 을 사용하는 table MYD, MYI, frm 확장자의 파일을 한 세트로 가진다. 5.5 InnoDB Default Engine 이기 때문에 사용자가 MyISAM Table 을 별도로 지정하지 않았다면 mysql schema table 이 유일한 MyISAM 테이블이 된다.

 

3.    Ways of Backup

A.     COPY

COPY 라 함은 OS cp, mv, rsync 등의 명령어를 사용한 백업을 말한다. MySQL   shutdown 된 상태라면 간단히 copy 만 해도 해당 시점의 온전한 데이터베이스를 얻을 수 있다. 하지만 동작중인 DB 라면 MyISAM 을 사용하는 Table 을 제외하고 온전한 백업을 얻을 수 없다. MyISAM 의 경우라 하더라도 lock table 명령을 사용해야 하므로 정상적인 서비스는 사용할 수 없게 된다.

 

B.     mysqldump

mysqldump free backup 도구이다. 백업 대상을 sql 형태로 뽑아낸다. 단점으로는 백업 대상이 된 타겟은 백업시간동안 Read only 상태가 된다는 것이다. 때문에 이 명령을 수행할 수 있는 시간은 한정적이다. 또한 백업하는 시간도 복구하는 시간도 오래 걸린다.

 

 

C.     ibbackup

핫백업 도구이다. 핫 백업이라 함은 서비스 타임에도 서비스 영향없이 사용할 수 있다는 이야기다. 이 도구는 mysqldump 와 달리 라이선스가 필요하다. 지금은 ORACLE SUN 을 샀고 SUN MySQL 을 가지고 있었기에 라이선스 정책은 ORACLE 이 가지고 있다. ibbackup 의 장점은 서비스에 영향없이 백업이 가능하다는 점과 (hot backup) mysqldump 와 비교했을 때 빠른 백업 / 복구 시간을 가진다는 점이다.

 

4.    Reason of Crashed Database

A.     USER

                i.         테이블 삭제

여기서 말하는 테이블 삭제는 사용자가 의도하지 않은 삭제를 말한다. ORACLE 의 경우 10g 부터 Recyclebin 이 생겨 복구가 가능하지만 MySQL 은 그렇지 않다.

 

               ii.         중요 파일 혹은 디렉토리 삭제

rm 명령을 실수로 사용한 것이 아니라면 일어날 수 없는 일들이다. Script 를 사용할 때는 경로를 주의해 사용해야 할 것이고 rm 과 같은 명령을 사용할 때에는 와일드 카드 대신 타겟을 명시적으로 사용하는게 예방책이라면 예방책이다.

 

B.     MACHINE

                i.         Page Corruption

디스크에 Corruption 이 있는 경우

쉽게 표현하면 디스크 블록에 문제가 있는 경우를 말한다. 디스크가 미러링 되어 있다면 자동복구 되겠지만 그렇지 않다면 복구 과정을 밟아야 한다. 미러링 되어 있더라도 소스가 전부 훼손된다거나(확률은 낮지만) 레이드가 풀리는 경우(역시 확률은 낮다.) 가 생기면 복구 과정을 밟을 수 밖에 없다.

 

MyISAM 테이블에 Corruption 이 있는 경우

Table Storage Engine MyISAM 을 사용하는 경우를 말한다.

 

InnoDB 테이블에 Corruption 이 있는 경우

Table Storage Engine InnoDB 를 사용하는 경우를 말한다.

 

Checksum Reset 을 이용한 방법

MySQL Page Corruption 을 발견하면 이를 해결하기위해 Instance Restart 한다. Restart 를 통해 Corruption 이 수정되면 다행이지만 그렇지 않은 경우에는 Restart 를 계속 반복하게 된다.

 

               ii.         중요 파일 혹은 디렉토리 손실

[hostname].index 파일의 경우

 

*.frm 파일의 경우

frm 파일은 해당 테이블의 구조정 정보를 담고 있다. 이 파일이 손상되면 데이터가 온전하더라도 읽을 수 없다.

 

Database Directory 의 경우

MySQL Database (=Schema) 는 디렉토리형태이며 해당 Database 가 소유한 Table 은 해당 디렉토리 안에 위치하게 된다. MyISAM Table 의 경우 MYD, MYI, frm 이 디렉토리 안에 위치하게 되며 InnoDB 의 경우는 frm 이 안에 위치하게 된다. (Index, Table Tablespace 에 위치한다.)

 

bin-log 의 경우

bin-log Optional 한 기능이지만 Replication 구성이라던가 Recover 에 필수 불가결하다.

 

MySQL Engine 이 분실된 경우

MySQL Engine 이 손상된 경우는 다른 경우에 비해 크리티컬하지 않다. 해당 내용은 다시 이야기 하도록 하겠다.

 

Redolog file 의 경우

Redolog file 이라 함은 InnoDB Redo log file 을 말한다. 이는 bin-log 와 다른것이다.

 

5.    SCENARIO

A.     테이블이 삭제된 경우

테이블이 의도하지 않게 삭제되었고 이 테이블을 이용하는 쿼리가 있다면 필연적으로 서비스가 영향을 받는다. 서비스가 영향을 받는다는 것은장애란 이야기다.

 

B.     디스크에 Corruption 이 있는 경우

데이터 영역이 미러링 되어 있다면 디스크에 일어난 Corruption 이 문제가 될 일은 희박하다. 그럼에도 불구하고 데이터 영역의 Corruption 이 문제가 된다는 것은 Mirroring 이 되어 있지 않다는 이야기다.

 

데이터 영역이라 함은 MySQL Engine 을 제외한 부분을 말한다. 데이터 파일에 손상이 갔기 때문에 복원 과정을 밟아야 하는데 먼저 미러링 구성을 다시 밟는다. 물론 이 내용은 물리적으로 다른 위치에 온전한 백업파일이 있음을 전제로 한다.

 

C.     MyISAM 테이블에 Corruption 이 있는 경우

check table / repair table 명령으로 처리한다.

 

D.     InnoDB 테이블에 Corruption 이 있는 경우

백업본을 이용하여 복구를 실시한다. 흐름은 핫백업본(ibbackup) 을 이용하는 것과 dump (mysqldump) 를 이용하는 방법이 있다.

 

E.     Checksum Reset 을 이용하여 Corruption 을 처리하는 경우

F.     [hostname].index 파일이 손상된 경우

G.    *.frm 파일이 손상된 경우

H.     bin-log 가 손상된 경우

I.       MySQL 엔진이 손상된 경우

J.      Redolog File 이 손상된 경우 (InnoDB)

 

6.     PRACTICE

A.     테이블이 삭제된 경우 서비스를 Stop 하고 진행하거나 그대로 진행하는 방법이 있다. 이것을 판단하는 기준은 테이블의 서비스에 대한 영향력과 관련있다.

그대로 진행한다는 것은 해당 테이블과 연관된 연산을 그대로 무시한다는 것이다. 동시에 이것은 에러를 감내할 수 있다라던가 별로 중요하지 않다란 말과 동일하다.

 

아래의 경우는 서비스를 막고 Recover 하는 과정의 예이다. fulldump Table 이 삭제되기 전의 백업이며 백업이후 테이블을 삭제하였다. 결과적으로 Binary Log 어딘가에 삭제구문이 들어있을 것이다.

 

 

mysql> source fulldump.sql

 

oracle32@/home/mysql/mysql1>head -n 50 fulldump.sql

-- MySQL dump 10.13  Distrib 5.5.8, for linux2.6 (i686)

--

-- Host: localhost    Database:

-- ------------------------------------------------------

-- Server version       5.5.8-enterprise-commercial-advanced-log

 

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

/*!40101 SET NAMES utf8 */;

/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;

/*!40103 SET TIME_ZONE='+00:00' */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;

/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

 

--

-- Position to start replication or point-in-time recovery from

--

 

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000033', MASTER_LOG_POS=107;

 

 

MySQL Dump 의 파일 내부를 살펴보면 위와같이 Binary Log / Binary Log Pos 정보를 볼 수 있다.

이를 통해 Binry Logs 가 어디까지 적용되어 있나 알 수 있다.

 

남은 문제는 어느 Binary Log 파일까지 적용할지에 대한 것과 어느 Position 까지 적용할지에 대한 문제이다.

 

oracle32@/home/mysql/mysql1>./bin/mysqlbinlog ./data/mysql-bin.000033 | grep DROP

 

위와 같은 방법으로 어느 Binary Logs 에서 실행되었는지 알 수 있다. binary log 는 말그대로 binary 파일로 myqlbinlog 를 통하지 않으면 파일내 sql 구문을 제대로 볼 수 없다.

 

grep DROP 명령어가 사용된 적 있는지 확인하기 위해 사용하였다.

 

DROP 이 어느 Bin log 에서 수행되었다는걸 확인하면 mysqlbinlog 와 출력자 지정을 통해 sql 구문으로 뽑아내는 과정을 밟는다.

 

oracle32@/home/mysql/mysql1>./bin/mysqlbinlog --start-position=107 ./data/mysql-bin.000033 > recover_f.sql

 

oracle32@/home/mysql/mysql1>vi recover_f.sql

 

vi 편집기에서 DROP 구문을 찾은 후 밑에줄을 잘라버린다

( command d + {매우 큰 숫자} + enter)

 

 

위의 과정을 통해 Drop 이 수행되기 이전까지의 SQL 을 얻을 수 있다.

 

recover_f.sql 을 통해 데이터를 넣었고 Table b_image 가 조회 가능함을 확인하였다. 아래에서는 recover_f.sql 을 수행하기 전/후 를 비교하였다.

 

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| bin_bak            |

| innodb_test        |

| mysql              |

| performance_schema |

| test               |

+--------------------+

6 rows in set (0.00 sec)

 

mysql> use test;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

 

Database changed

mysql> show tables;

+----------------+

| Tables_in_test |

+----------------+

| id             |

| id1            |

| id2            |

| sample         |

+----------------+

4 rows in set (0.00 sec)

 

mysql> source recover_f.sql

 

Database changed

mysql> show tables;

+----------------+

| Tables_in_test |

+----------------+

| b_image        |

| id             |

| id1            |

| id2            |

| sample         |

+----------------+

5 rows in set (0.00 sec)

 

mysql> select * from b_image;

+--------------+

| a            |

+--------------+

| before image |

+--------------+

1 row in set (0.00 sec)

 

 

 

B.     디스크에 Corruption 이 있는 경우

사전에 다음의 백업을 가지고 있다고 가정한다.

-      MySQL Engine Backup

-      my.cnf

-      MyISAM Backup

-      InnoDB Backup (ibbackup)

-      binary log Backup

 

Backup 본은 sqldump 도 사용가능하다. sqldump 의 경우는 A 에서 이야기 한 것과 흐름은 동일하다.

ibbackup sqldump 와 달리 복구 소요시간이 짧기 때문에 1차적인 선택안이 된다.

 

먼저 기존에 Backup 본이 있다고 가정한다. 백업본의 위치는 data2 이며 이를 data 에 위치한 innodb file 에 덮어씌운다.

 

ibbackup: We were able to parse ibbackup_logfile up to

ibbackup: lsn 0 8283158

ibbackup: Last MySQL binlog file position 0 561, file name ./mysql-bin.000005

ibbackup: The first data file is '/home/mysql/mysql/data2/ibdata1'

ibbackup: and the new created log files are at '/home/mysql/mysql/data2/'

110517 17:51:15  ibbackup: Full backup prepared for recovery successfully!

 

oracle32@/home/mysql/mysql/data2>mv * ../data/

 

 

ibbackup 을 실시했을 때 binlog file position 정보가 나온다. 이 정보는 백업본을 사용했을 때 다시 나오기 때문에 외울 필요성은 없다.

 

InnoDB 를 덮어 씌운 후 startup 을 하면 error log 에 다음과 같은 메시지를 확인할 수 있다.

 

110517 17:54:22  InnoDB: Database was not shut down normally!

InnoDB: Starting crash recovery.

InnoDB: Reading tablespace information from the .ibd files...

InnoDB: Restoring possible half-written data pages from the doublewrite

InnoDB: buffer...

InnoDB: Last MySQL binlog file position 0 561, file name ./mysql-bin.000005

110517 17:54:22  InnoDB: 1.1.4 started; log sequence number 8283660

110517 17:54:22 [Note] Event Scheduler: Loaded 0 events

 

위의 내용에 binlog file / position 정보가 나옴을 확인할 수 잇다.

위 정보를 토대로 가장 최근시점까지의 갭을 알 수 있다.

 

mysql> show binary logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000001 |     27838 |

| mysql-bin.000002 |    993661 |

| mysql-bin.000003 |       126 |

| mysql-bin.000004 |   1222768 |

| mysql-bin.000005 |       580 |

| mysql-bin.000006 |       126 |

| mysql-bin.000007 |       107 |

+------------------+-----------+

7 rows in set (0.00 sec)

 

binary logs 를 조회한 결과 가장최근의 파일이 7번임을 알 수 있었다.

 

oracle32@/home/mysql/mysql>./bin/mysqlbinlog --start-position=561 ./data/mysql-bin.000005 ./data/mysql-bin.000006 ./data/mysql-bin.000007 >>recover.sql

 

위 정보를 통해 recover 에 필요한 정보를 sql 로 만든다. 이 정보는 서버에서 수행하면 된다.

mysql> set sql_log_bin=0;

 

mysql> source recover.sql

 

참고로 recover 하기 위해 만든 쿼리를 sql_log_bin=0 셋팅없이 수행하면 binary log 를 쌓게 된다. 장애복구를 하고나면 바로 백업을 실시해야 되지만 그렇지 않은 경우 또 다음 풀백업 전에 또다시 장애가 났고 사용했던 binary log 를 또 사용해야 한다면 dml 이 중첩된 binary log 를 사용하게 된다. (이런 일이 일어날 일은 낮지만 sql_log_bin 을 셋팅해 둬서 나쁠일은 없다.)

 

C.     MyISAM 테이블에 Corruption 이 있는 경우

check table 을 실시한다. 여기서는 check table option 에 대한 설명은 따로 하지 않겠다. 핵심은 이 명령어를 통해 Corruption 검사가 가능하다는 것이다.

mysql> check table db for upgrade;

+----------+-------+----------+----------+

| Table    | Op    | Msg_type | Msg_text |

+----------+-------+----------+----------+

| mysql.db | check | status   | OK       |

+----------+-------+----------+----------+

1 row in set (0.01 sec)

 

mysql> check table db quick;

+----------+-------+----------+----------+

| Table    | Op    | Msg_type | Msg_text |

+----------+-------+----------+----------+

| mysql.db | check | status   | OK       |

+----------+-------+----------+----------+

1 row in set (0.00 sec)

 

mysql> check table db fast;

+----------+-------+----------+-----------------------------+

| Table    | Op    | Msg_type | Msg_text                    |

+----------+-------+----------+-----------------------------+

| mysql.db | check | status   | Table is already up to date |

+----------+-------+----------+-----------------------------+

1 row in set (0.00 sec)

 

mysql> check table db medium;

+----------+-------+----------+----------+

| Table    | Op    | Msg_type | Msg_text |

+----------+-------+----------+----------+

| mysql.db | check | status   | OK       |

+----------+-------+----------+----------+

1 row in set (0.00 sec)

 

mysql> check table db extended;

+----------+-------+----------+----------+

| Table    | Op    | Msg_type | Msg_text |

+----------+-------+----------+----------+

| mysql.db | check | status   | OK       |

+----------+-------+----------+----------+

1 row in set (0.00 sec)

 

mysql> check table db changed;

+----------+-------+----------+-----------------------------+

| Table    | Op    | Msg_type | Msg_text                    |

+----------+-------+----------+-----------------------------+

| mysql.db | check | status   | Table is already up to date |

+----------+-------+----------+-----------------------------+

1 row in set (0.00 sec)

 

Corruption 이 확인되었다면 repair table 을 실시한다.

mysql> repair local table db;

+----------+--------+----------+----------+

| Table    | Op     | Msg_type | Msg_text |

+----------+--------+----------+----------+

| mysql.db | repair | status   | OK       |

+----------+--------+----------+----------+

1 row in set (0.00 sec)

 

mysql> repair no_write_to_binlog table db;

+----------+--------+----------+----------+

| Table    | Op     | Msg_type | Msg_text |

+----------+--------+----------+----------+

| mysql.db | repair | status   | OK       |

+----------+--------+----------+----------+

1 row in set (0.00 sec)

 

mysql> repair local table db quick;

+----------+--------+----------+----------+

| Table    | Op     | Msg_type | Msg_text |

+----------+--------+----------+----------+

| mysql.db | repair | status   | OK       |

+----------+--------+----------+----------+

1 row in set (0.00 sec)

 

mysql> repair local table db extended;

+----------+--------+----------+----------+

| Table    | Op     | Msg_type | Msg_text |

+----------+--------+----------+----------+

| mysql.db | repair | status   | OK       |

+----------+--------+----------+----------+

1 row in set (0.00 sec)

 

mysql> repair local table db use_frm;

+----------+--------+----------+------------------------------------+

| Table    | Op     | Msg_type | Msg_text                           |

+----------+--------+----------+------------------------------------+

| mysql.db | repair | warning  | Number of rows changed from 0 to 2 |

| mysql.db | repair | status   | OK                                 |

+----------+--------+----------+------------------------------------+

2 rows in set (0.00 sec)

 

D.     InnoDB 테이블에 Corruption 이 있는 경우

핫백업이 있는 경우엔 B 의 과정과 동일하다.

핫백업이 없는 경우엔 mysqldump 를 이용해야 하는데 A 와 동일한 과정을 밟는다.

 

E.     Checksum Reset 을 이용하여 Corruption 을 처리하는 경우

/*+ 테스트 케이스 추가 */

 

F.     [hostname].index 파일이 손상된 경우

mysql-bin.index 가 손상된 경우 Standalone (ORACLE Single Instance 를 생각) 의 경우 별 문제 없으며 Instance 재기동시 파일도 정상적으로 생성된다.

 

다만 Replication 의 경우 binary log 를 이용해 Slave 에 전달하기 때문에 정합성이 깨질 수 있다.

 

아래의 예시는 mysql-bin.index 를 다른 위치로 이동시킬 때 mysql 상에 나타나는 변화를 확인해 본 결과이다.

 

oracle32@/home/mysql/mysql2/data>ls

ibbackup_logfile  mysql             mysql-bin.000004  oracle32.test.com.err

ibdata1           mysql-bin.000001  mysql-bin.000005  oracle32.test.com.pid

ib_logfile0       mysql-bin.000002  mysql-bin.000006  performance_schema

ib_logfile1       mysql-bin.000003  mysql-bin.index   test

oracle32@/home/mysql/mysql2/data>mv mysql-bin.index ../../

 

oracle32@/home/mysql/mysql2>./bin/mysql -uroot

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 2

Server version: 5.5.8-enterprise-commercial-advanced-log MySQL Enterprise Server - Advanced Edition (Commercial)

 

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 

mysql> show binary logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000001 |     27838 |

| mysql-bin.000002 |    993661 |

| mysql-bin.000003 |       126 |

| mysql-bin.000004 |   1222768 |

| mysql-bin.000005 |       126 |

| mysql-bin.000006 |       107 |

+------------------+-----------+

6 rows in set (0.00 sec)

 

 

위 결과를 보면 mysql-bin.index 파일을 mv 시켰음에도 불구하고 show binary logs 조회 했을 때 내용이 다 출력됨을 알 수 있었다.

 

아래 결과는 데이터베이스를 내렸다 올린 시점의 결과이며 mv 했던 mysql-bin.index 파일이 재생성 되었음을 알 수 있다. 다만 binary logs 를 조회했을 때 Binary Logs 6번에서 7번으로 바뀌었고 7번 이전은 파일 시스템에 존재함에도 불구하고 없는것으로 나온다.

 

Replication Master 에서 이와 같은 일이 일어났다고 하면 Slave 측에서는 손실된 Binary log file 의 정보를 요구하는 상황이 벌어질 수 있다.

 

oracle32@/home/mysql/mysql2/data>ls

ibbackup_logfile  mysql             mysql-bin.000004  mysql-bin.index        test

ibdata1           mysql-bin.000001  mysql-bin.000005  oracle32.test.com.err

ib_logfile0       mysql-bin.000002  mysql-bin.000006  oracle32.test.com.pid

ib_logfile1       mysql-bin.000003  mysql-bin.000007  performance_schema

 

oracle32@/home/mysql/mysql2>./bin/mysql -uroot

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 1

Server version: 5.5.8-enterprise-commercial-advanced-log MySQL Enterprise Server - Advanced Edition (Commercial)

 

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 

mysql> show binary logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000007 |       107 |

+------------------+-----------+

1 row in set (0.00 sec)

 

 

 

G.    *.frm 파일이 손상된 경우

frm 파일은 Table Dictionary 정보를 가지고 있으며 이 파일이 손상되는 경우 Table Access 가 불가능해 진다.

 

oracle32@/home/mysql/mysql2>mv ./data/test/City.frm ./data/test/City

 

mysql> use test;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

 

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test  |

+-----------------+

| Country         |

| CountryLanguage |

+-----------------+

2 rows in set (0.00 sec)

 

mysql> select * from City;

ERROR 1146 (42S02): Table 'test.City' doesn't exist

 

 

위에서 frm 파일을 이동시키자 City table 이 보이지 않게 되었고 접근도 불가능했다.

 

oracle32@/home/mysql/mysql2>mv ./data/test/City ./data/test/City.frm

 

mysql> use test;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

 

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test  |

+-----------------+

| City            |

| Country         |

| CountryLanguage |

+-----------------+

3 rows in set (0.00 sec)

 

mysql> select count(*) from City;

+----------+

| count(*) |

+----------+

|     4079 |

+----------+

1 row in set (0.00 sec)

 

 

frm 파일을 원래대로 복원하자 Table 이 다시 보였고 Access 도 가능했다.

 

위와 같은 복구는 Table 의 구조적 정보 (이를 테면 컬럼 같은…) 변경이 없었을 때 가능하며 물리적 구조가 변경이 된 경우에는 변경 이후의 frm 파일이 필요하다. 이것이 없는 경우 백업해 둔 frm 을 사용하되 Access 가 되는지 확인하며 이 방법도 안된다면 의도하지 않은 Table 삭제 때와 동일한 복구 절차를 밟아야 한다.

 

H.     bin-log 가 손상된 경우

bin-log Optional 한 기능으로 손상되어도 큰 문제는 없다. 다만 추후 Recover 시에 문제가 될 수 있다. InnoDB 의 경우 ib logfile Instance Recovery 역할을 하기에 문제가 없지만 다른 Type Storage Engine 은 그렇지 않다. Replication 의 경우 bin log 에서 Slave DML 이 전파되기 때문에 Master Data 가 달라질 수 있다.

 

운영중 Binary Log 에 문제가 생기면 Flush 를 해 다시 로그를 쌓도록 만들어야 한다.

 

다음의 예시는 mysql-bin.000009 OS 상에서 삭제후 world_innodb.sql 을 통해 data insert 한 후의 File_size 이다.

 

mysql> show binary logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000007 |       150 |

| mysql-bin.000008 |       150 |

| mysql-bin.000009 |   1223081 |

+------------------+-----------+

3 rows in set (0.00 sec)

 

mysql> exit

Bye

oracle32@/home/mysql/mysql2>cd data

oracle32@/home/mysql/mysql2/data>ls

ibbackup_logfile  mysql-bin.000001  mysql-bin.000006       oracle32.test.com.pid

ibdata1           mysql-bin.000002  mysql-bin.000007       performance_schema

ib_logfile0       mysql-bin.000003  mysql-bin.000008       test

ib_logfile1       mysql-bin.000004  mysql-bin.index

mysql             mysql-bin.000005  oracle32.test.com.err

 

 

world_innodb.sql 을 실행하면서 mysql-bin.000009 의 크기도 증가했지만 파일 시스템 상을 확인해 본 결과 binary log file 자체가 없음을 알 수 있었다.

 

mysql> flush logs;

Query OK, 0 rows affected (0.00 sec)

 

mysql> show binary logs;

+------------------+-----------+

| Log_name         | File_size |

+------------------+-----------+

| mysql-bin.000007 |       150 |

| mysql-bin.000008 |       150 |

| mysql-bin.000009 |       107 |

| mysql-bin.000009 |       107 |

+------------------+-----------+

5 rows in set (0.00 sec)

oracle32@/home/mysql/mysql2>cd data

oracle32@/home/mysql/mysql2/data>ls

ibbackup_logfile  mysql-bin.000001  mysql-bin.000006  oracle32.test.com.err

ibdata1           mysql-bin.000002  mysql-bin.000007  oracle32.test.com.pid

ib_logfile0       mysql-bin.000003  mysql-bin.000008  performance_schema

ib_logfile1       mysql-bin.000004  mysql-bin.000009  test

mysql             mysql-bin.000005  mysql-bin.index

 

 

binary log flush logs 를 실행하면 Binary log 를 재생성한다. binary logs 가 쌓이지 않은 시점부터 재생성까지는 정보가 손실된 것이다. 물론 Optional 한 기능인 만큼 Database 를 복원하는 경우가 아니라면 이슈가 되지 않지만 Binary log 를 사용하여 Recover 과정을 밟아야 한다면 이 부분은 손실되었기 때문에 문제가 된다.

 

I.       MySQL 엔진이 손상된 경우

MySQL Engine 을 메모리에 로드하기 때문에 Engine 이 손상되어도 정상적으로 동작한다. Instance 를 내리기 전에 백업해 둔 Engine 을 복원하면 된다.

 

 

oracle32@/home/mysql/mysql2>ps -ef | grep mysql

root      4912  4394  0 15:31 pts/1    00:00:00 su - mysql

mysql     4913  4912  0 15:31 pts/1    00:00:00 -ksh

mysql    12312  4913  0 18:13 pts/1    00:00:00 /bin/sh ./bin/mysqld_safe --defaults-file=/home/mysql/mysql2/conf/my.cnf

mysql    12635 12312  0 18:13 pts/1    00:00:06 /home/mysql/mysql2/bin/mysqld --defaults-file=/home/mysql/mysql2/conf/my.cnf --basedir=/home/mysql/mysql2 --datadir=/home/mysql/mysql2/data --plugin-dir=/home/mysql/mysql2/lib/plugin --log-error=/home/mysql/mysql2/data/oracle32.test.com.err --pid-file=/home/mysql/mysql2/data/oracle32.test.com.pid --socket=/tmp/mysql.sock --port=3306

mysql    19770  4913  0 22:27 pts/1    00:00:00 ps -ef

oracle32@/home/mysql/mysql2>

oracle32@/home/mysql/mysql2>

oracle32@/home/mysql/mysql2>

oracle32@/home/mysql/mysql2>ls

2     data     INSTALL-BINARY  man         scripts    support-files

bin   docs     lib             mysql-test  share      world_innodb.sql

conf  include  LICENSE.mysql   README      sql-bench

oracle32@/home/mysql/mysql2>rm -rf bin docs include lib man mysql-test scripts share sql-bench support-files

oracle32@/home/mysql/mysql2>ls

2  conf  data  INSTALL-BINARY  LICENSE.mysql  README  world_innodb.sql

 

oracle32@/home/mysql/mysql2>ps -ef | grep mys

root      4912  4394  0 15:31 pts/1    00:00:00 su - mysql

mysql     4913  4912  0 15:31 pts/1    00:00:00 -ksh

mysql    12312  4913  0 18:13 pts/1    00:00:00 /bin/sh ./bin/mysqld_safe --defaults-file=/home/mysql/mysql2/conf/my.cnf

mysql    12635 12312  0 18:13 pts/1    00:00:06 /home/mysql/mysql2/bin/mysqld --defaults-file=/home/mysql/mysql2/conf/my.cnf --basedir=/home/mysql/mysql2 --datadir=/home/mysql/mysql2/data --plugin-dir=/home/mysql/mysql2/lib/plugin --log-error=/home/mysql/mysql2/data/oracle32.test.com.err --pid-file=/home/mysql/mysql2/data/oracle32.test.com.pid --socket=/tmp/mysql.sock --port=3306

mysql    19823  4913  0 22:28 pts/1    00:00:00 ps -ef

 

oracle32@/home/mysql/mysql>ls

bin   data2    INSTALL-BINARY  man         scripts    support-files

conf  docs     lib             mysql-test  share      world_innodb.sql

data  include  LICENSE.mysql   README      sql-bench

oracle32@/home/mysql/mysql>cp -R bin ../mysql2

oracle32@/home/mysql/mysql>cp -R conf ../mysql2

oracle32@/home/mysql/mysql>cp -R docs ../mysql2

oracle32@/home/mysql/mysql>cp -R include ../mysql2

oracle32@/home/mysql/mysql>cp -R lib ../mysql2

oracle32@/home/mysql/mysql>cp -R man ../mysql2

oracle32@/home/mysql/mysql>cp -R mysql-test ../mysql2

oracle32@/home/mysql/mysql>cp -R share ../mysql2

oracle32@/home/mysql/mysql>cp -R sql-bench ../mysql2

oracle32@/home/mysql/mysql>cp -R support-files ../mysql2

oracle32@/home/mysql/mysql>cd ../mysql2

oracle32@/home/mysql/mysql2>ls

2     data     INSTALL-BINARY  man         share          world_innodb.sql

bin   docs     lib             mysql-test  sql-bench

conf  include  LICENSE.mysql   README      support-files

oracle32@/home/mysql/mysql2>./bin/mysql -uroot

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 9

Server version: 5.5.8-enterprise-commercial-advanced-log MySQL Enterprise Server - Advanced Edition (Commercial)

 

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| performance_schema |

| test               |

+--------------------+

4 rows in set (0.00 sec)

 

mysql> use test;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

 

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test  |

+-----------------+

| City            |

| Country         |

| CountryLanguage |

+-----------------+

3 rows in set (0.00 sec)

 

Engine 을 삭제했다가 다시 복원한 후 MySQL 에 접속했을 때 아무런 이상이 없었음을 알 수 있었다.

 

J.      Redolog File 이 손상된 경우 (InnoDB)

oracle32@/home/mysql/mysql/data>rm ib_logfile1

oracle32@/home/mysql/mysql>./bin/mysql -uroot

 

mysql> insert into hello values('1123');

Query OK, 1 row affected (0.00 sec)

 

 

ib_logfile1 OS 에서 삭제하였다. 이상태에서 MySQL 접속도 가능했으며 value 입력도 가능했다.

 

 

110517 17:23:18 mysqld_safe mysqld from pid file /home/mysql/mysql/data/oracle32.test.com.pid ended

110517 17:25:00 mysqld_safe Starting mysqld daemon with databases from /home/mysql/mysql/data

110517 17:25:00 [Note] Plugin 'FEDERATED' is disabled.

InnoDB: The InnoDB memory heap is disabled

InnoDB: Mutexes and rw_locks use InnoDB's own implementation

InnoDB: Compressed tables use zlib 1.2.3

110517 17:25:00  InnoDB: Using Linux native AIO

110517 17:25:00  InnoDB: Initializing buffer pool, size = 16.0M

110517 17:25:00  InnoDB: Completed initialization of buffer pool

InnoDB: Error: log file /home/mysql/mysql/data/ib_logfile1 is of different size 0 0 bytes

InnoDB: than specified in the .cnf file 0 5242880 bytes!

110517 17:25:00 [ERROR] Plugin 'InnoDB' init function returned error.

110517 17:25:00 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.

110517 17:25:00 [ERROR] Unknown/unsupported storage engine: InnoDB

110517 17:25:00 [ERROR] Aborting

 

110517 17:25:00 [Note] /home/mysql/mysql/bin/mysqld: Shutdown complete

 

110517 17:25:00 mysqld_safe mysqld from pid file /home/mysql/mysql/data/oracle32.test.com.pid ended

 

 

shutdown startup 을 하고자 하니 위와 같은 에러가나며 abort 되었다.

 

oracle32@/home/mysql/mysql/data>ls -lrt

total 25824

drwx------ 2 mysql mysql     4096 May 15 16:06 performance_schema

-rw-rw---- 1 mysql mysql   993661 May 15 16:06 mysql-bin.000002

-rw-rw---- 1 mysql mysql    27838 May 15 16:06 mysql-bin.000001

drwxr-xr-x 2 mysql mysql     4096 May 15 16:06 mysql

-rw-rw---- 1 mysql mysql      126 May 15 16:10 mysql-bin.000003

-rw-rw---- 1 mysql mysql  1222768 May 15 16:34 mysql-bin.000004

-rw-rw---- 1 mysql mysql       95 May 17 16:59 mysql-bin.index

drwxr-xr-x 2 mysql mysql     4096 May 17 17:20 test

-rw-rw---- 1 mysql mysql      580 May 17 17:22 mysql-bin.000005

-rw-rw---- 1 mysql mysql  5242880 May 17 17:22 ib_logfile0

-rw-rw---- 1 mysql mysql 18874368 May 17 17:22 ibdata1

-rw-rw---- 1 mysql mysql        0 May 17 17:22 ib_logfile1

-rw-rw---- 1 mysql mysql     7919 May 17 17:25 oracle32.test.com.err

 

oracle32@/home/mysql/mysql/data>rm -rf ib_logfile*

 

 

ls -lrt 의 결과를 보니 ib_logfile 의 생성일시는 동일하나 ib_logfile1 에 데이터가 존재하지 않는다. 남아있는 ib_logfile 을 전부 삭제후 다시 start 해보았다.

 

oracle32@/home/mysql/mysql/data>ls -lrt

total 30968

drwx------ 2 mysql mysql     4096 May 15 16:06 performance_schema

-rw-rw---- 1 mysql mysql   993661 May 15 16:06 mysql-bin.000002

-rw-rw---- 1 mysql mysql    27838 May 15 16:06 mysql-bin.000001

drwxr-xr-x 2 mysql mysql     4096 May 15 16:06 mysql

-rw-rw---- 1 mysql mysql      126 May 15 16:10 mysql-bin.000003

-rw-rw---- 1 mysql mysql  1222768 May 15 16:34 mysql-bin.000004

drwxr-xr-x 2 mysql mysql     4096 May 17 17:20 test

-rw-rw---- 1 mysql mysql      580 May 17 17:22 mysql-bin.000005

-rw-rw---- 1 mysql mysql 18874368 May 17 17:22 ibdata1

-rw-rw---- 1 mysql mysql        5 May 17 17:29 oracle32.test.com.pid

-rw-rw---- 1 mysql mysql     9711 May 17 17:29 oracle32.test.com.err

-rw-rw---- 1 mysql mysql      114 May 17 17:29 mysql-bin.index

-rw-rw---- 1 mysql mysql      107 May 17 17:29 mysql-bin.000006

-rw-rw---- 1 mysql mysql  5242880 May 17 17:29 ib_logfile1

-rw-rw---- 1 mysql mysql  5242880 May 17 17:29 ib_logfile0

 

mysql> show tables;

+-----------------+

| Tables_in_test  |

+-----------------+

| City            |

| Country         |

| CountryLanguage |

| hello           |

+-----------------+

4 rows in set (0.00 sec)

 

mysql> select * from hello;

+------+

| id   |

+------+

| 1121 |

| 1122 |

| 1123 |

+------+

3 rows in set (0.00 sec)

 

 

ib logfile 이 재생성되었고 mysql 도 이상없이 Startup 되었다. ib logfile 삭제 직전에 입력했던 데이터 1123 도 이상없이 조회되는 것을 확인하였다.