mysql 8 복구( ibd 이용, frm 없음 )

갑자기 정말롱 아무 이유없이 mysql이 망가졌다.

서버를 내리지도 않았고 mysql을 멈추지도 않았는데 혼자서 뻑났다.

mysql 에 접속할 수 없기 때문에  dump 를 뜰 수도 없고 망연자실...

그나마 다행인건 블로그등 was 쪽은 다른 물리서버에 있기 때문에 mysql만 문제되는거 같았다.

갖은 방법을 찾다가  ibd 파일들로 복구하는 방법으로 성공하여 포스팅한다.

증상

mysql을 실행하면

ERROR 2002 (HY000) : Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’ (2)

라며 구동이 되질 않는다. 해당 파일 위치에 가면 파일이 없다.

/tmp/mysql.sock 를 심볼릭 링크로 연결한 파일이란다.

수동으로 파일을 생성해 보려 했더니 넣어야 하는 스크립트가 너무 많다. ( 슬슬 짜증 )

mysql을 삭제하고 클린설치를 할랬더니 삭제도 안된다. 의존 리파지토리에서 불러올수가 없다는 에러들이 뜸.  apt-update 조차도 에러들이 발생했다.
( 아 뭔가 단단히 꼬였구나 직감 )

해결찾아 삼만리

" mysql 도 어차피 파일에 데이터를 기록하지 않을까? 그걸로 복구는 안될까?" 의문을 던짐

친절한 구글씨는 "/var/lib/mysql/" 에  mysql 파일들 모여있어~ 라고 알려준다.

언능 해당 폴더로 가봤다.

고스트 블로그와 토이 프로젝트  db 로 추측되는 폴더들이 보인다. 두근거리기 시작.

우선  /var/lib/mysql 폴더를 tar 로 압축해서 다른 서버에 복사( scp )했다.

  1. 고스트 블로그 등 mysql 사용하던 서비스 중지( ghost stop, sudo service 해당서비스 stop )
  2. 문제된 서버에 우분투 클린설치
  3. mysql 설치
  4. mysql 에 고스트 블로그 db 생성, 유저 생성
  5. 고스트 재기동( ghost start )
  6. 고스트가 구동되면서 mysql 초기화를 하고 사이트 뜨는걸 확인
  7. ghost stop
  8. 백업했던 mysql 폴더의 파일들을 클린설치된 서버의 /var/lib/mysql 에 덮어쓰기

( 6번 ibd 파일들을 이용하여 복구하려면 해당 스키마가 이전대로 복원이 된 상태여만 가능해서 고스트 초기화로 해당 테이블들을 만들어 둬야 하기 때문. frm 파일들이 있으면 이 짓을 할 필요가 없어 보이는데 어째서인지 frm 파일들이 하나도 없었다 )

/var/lib/mysql

파일들을 복구했으면 이제 sql 쿼리를 이용하여 실제 복구를 진행한다.

고스트에서 사용하는 db로 들어가서 show tables; 를 하자.

고스트 구동시 초기화된 테이블 구조들이 보인다.

ALTER TABLE [테이블명] DISCARD TABLESPACE
ALTER TABLE [테이블명] IMPORT TABLESPACE;

이 2개가 ibd 파일의 내용을 읽어서 해당 테이블에 복구시켜주는 쿼리이다.

근데 이걸 실행하면 "Cannot delete or update a parent row: a foreign key constraint fails" 가 발생한다. "SET foreign_key_checks = 0;" 를 통해서 임시 해제 후 복구하면 된다.

아래는 실행했던 full query 이다.( ghost 5.8.3 기준 )

show tables;--테이블 목록 확인

SET foreign_key_checks = 0;

ALTER TABLE actions DISCARD TABLESPACE;
ALTER TABLE api_keys DISCARD TABLESPACE;
ALTER TABLE benefits DISCARD TABLESPACE;
ALTER TABLE brute DISCARD TABLESPACE;
ALTER TABLE comment_likes DISCARD TABLESPACE;
ALTER TABLE comment_reports DISCARD TABLESPACE;
ALTER TABLE comments DISCARD TABLESPACE;
ALTER TABLE custom_theme_settings DISCARD TABLESPACE;
ALTER TABLE email_batches DISCARD TABLESPACE;
ALTER TABLE email_recipients DISCARD TABLESPACE;
ALTER TABLE emails DISCARD TABLESPACE;
ALTER TABLE integrations DISCARD TABLESPACE;
ALTER TABLE invites DISCARD TABLESPACE;
ALTER TABLE jobs DISCARD TABLESPACE;
ALTER TABLE labels DISCARD TABLESPACE;
ALTER TABLE members DISCARD TABLESPACE;
ALTER TABLE members_cancel_events DISCARD TABLESPACE;
ALTER TABLE members_email_change_events DISCARD TABLESPACE;
ALTER TABLE members_labels DISCARD TABLESPACE;
ALTER TABLE members_login_events DISCARD TABLESPACE;
ALTER TABLE members_newsletters DISCARD TABLESPACE;
ALTER TABLE members_paid_subscription_events DISCARD TABLESPACE;
ALTER TABLE members_payment_events DISCARD TABLESPACE;
ALTER TABLE members_product_events DISCARD TABLESPACE;
ALTER TABLE members_products DISCARD TABLESPACE;
ALTER TABLE members_status_events DISCARD TABLESPACE;
ALTER TABLE members_stripe_customers DISCARD TABLESPACE;
ALTER TABLE members_stripe_customers_subscriptions DISCARD TABLESPACE;
ALTER TABLE members_subscribe_events DISCARD TABLESPACE;
ALTER TABLE migrations DISCARD TABLESPACE;
ALTER TABLE migrations_lock DISCARD TABLESPACE;
ALTER TABLE mobiledoc_revisions DISCARD TABLESPACE;
ALTER TABLE newsletters DISCARD TABLESPACE;
ALTER TABLE offer_redemptions DISCARD TABLESPACE;
ALTER TABLE offers DISCARD TABLESPACE;
ALTER TABLE permissions DISCARD TABLESPACE;
ALTER TABLE permissions_roles DISCARD TABLESPACE;
ALTER TABLE permissions_users DISCARD TABLESPACE;
ALTER TABLE posts DISCARD TABLESPACE;
ALTER TABLE posts_authors DISCARD TABLESPACE;
ALTER TABLE posts_meta DISCARD TABLESPACE;
ALTER TABLE posts_products DISCARD TABLESPACE;
ALTER TABLE posts_tags DISCARD TABLESPACE;
ALTER TABLE products DISCARD TABLESPACE;
ALTER TABLE products_benefits DISCARD TABLESPACE;
ALTER TABLE roles DISCARD TABLESPACE;
ALTER TABLE roles_users DISCARD TABLESPACE;
ALTER TABLE sessions DISCARD TABLESPACE;
ALTER TABLE settings DISCARD TABLESPACE;
ALTER TABLE snippets DISCARD TABLESPACE;
ALTER TABLE stripe_prices DISCARD TABLESPACE;
ALTER TABLE stripe_products DISCARD TABLESPACE;
ALTER TABLE tags DISCARD TABLESPACE;
ALTER TABLE tokens DISCARD TABLESPACE;
ALTER TABLE users DISCARD TABLESPACE;
ALTER TABLE webhooks DISCARD TABLESPACE;

ALTER TABLE actions IMPORT TABLESPACE;
ALTER TABLE api_keys IMPORT TABLESPACE;
ALTER TABLE benefits IMPORT TABLESPACE;
ALTER TABLE brute IMPORT TABLESPACE;
ALTER TABLE comment_likes IMPORT TABLESPACE;
ALTER TABLE comment_reports IMPORT TABLESPACE;
ALTER TABLE comments IMPORT TABLESPACE;
ALTER TABLE custom_theme_settings IMPORT TABLESPACE;
ALTER TABLE email_batches IMPORT TABLESPACE;
ALTER TABLE email_recipients IMPORT TABLESPACE;
ALTER TABLE emails IMPORT TABLESPACE;
ALTER TABLE integrations IMPORT TABLESPACE;
ALTER TABLE invites IMPORT TABLESPACE;
ALTER TABLE jobs IMPORT TABLESPACE;
ALTER TABLE labels IMPORT TABLESPACE;
ALTER TABLE members IMPORT TABLESPACE;
ALTER TABLE members_cancel_events IMPORT TABLESPACE;
ALTER TABLE members_email_change_events IMPORT TABLESPACE;
ALTER TABLE members_labels IMPORT TABLESPACE;
ALTER TABLE members_login_events IMPORT TABLESPACE;
ALTER TABLE members_newsletters IMPORT TABLESPACE;
ALTER TABLE members_paid_subscription_events IMPORT TABLESPACE;
ALTER TABLE members_payment_events IMPORT TABLESPACE;
ALTER TABLE members_product_events IMPORT TABLESPACE;
ALTER TABLE members_products IMPORT TABLESPACE;
ALTER TABLE members_status_events IMPORT TABLESPACE;
ALTER TABLE members_stripe_customers IMPORT TABLESPACE;
ALTER TABLE members_stripe_customers_subscriptions IMPORT TABLESPACE;
ALTER TABLE members_subscribe_events IMPORT TABLESPACE;
ALTER TABLE migrations IMPORT TABLESPACE;
ALTER TABLE migrations_lock IMPORT TABLESPACE;
ALTER TABLE mobiledoc_revisions IMPORT TABLESPACE;
ALTER TABLE newsletters IMPORT TABLESPACE;
ALTER TABLE offer_redemptions IMPORT TABLESPACE;
ALTER TABLE offers IMPORT TABLESPACE;
ALTER TABLE permissions IMPORT TABLESPACE;
ALTER TABLE permissions_roles IMPORT TABLESPACE;
ALTER TABLE permissions_users IMPORT TABLESPACE;
ALTER TABLE posts IMPORT TABLESPACE;
ALTER TABLE posts_authors IMPORT TABLESPACE;
ALTER TABLE posts_meta IMPORT TABLESPACE;
ALTER TABLE posts_products IMPORT TABLESPACE;
ALTER TABLE posts_tags IMPORT TABLESPACE;
ALTER TABLE products IMPORT TABLESPACE;
ALTER TABLE products_benefits IMPORT TABLESPACE;
ALTER TABLE roles IMPORT TABLESPACE;
ALTER TABLE roles_users IMPORT TABLESPACE;
ALTER TABLE sessions IMPORT TABLESPACE;
ALTER TABLE settings IMPORT TABLESPACE;
ALTER TABLE snippets IMPORT TABLESPACE;
ALTER TABLE stripe_prices IMPORT TABLESPACE;
ALTER TABLE stripe_products IMPORT TABLESPACE;
ALTER TABLE tags IMPORT TABLESPACE;
ALTER TABLE tokens IMPORT TABLESPACE;
ALTER TABLE users IMPORT TABLESPACE;
ALTER TABLE webhooks IMPORT TABLESPACE;

SET foreign_key_checks = 1;

복원 후 너무 노가다가 아닌가? 하는 의심이 들어 찾아보니 아니나 다를까 반복문으로 간단히 하는 방법이 있었다.

#!/bin/bash
db_user="root"
db_pass="[DB root 패스워드]"

database="[복구할 데이터베이스명]"

for table in `mysql -u${db_user} -p${db_pass}  -e"show tables" $database | /bin/grep -v "^$" | /bin/grep -v "Tables_in_$database"`
do
       echo "${table} 복구시도..."
       mysql -u${db_user} -p${db_pass} -e "use $database; SET foreign_key_checks = 0; ALTER TABLE ${table} DISCARD TABLESPACE; flush privileges;"
       cp -arp [백업해놓은 ibd 파일 디렉터리]/${table}.ibd [실제 ibd 파일이 위치할 경로]
       mysql -u${db_user} -p${db_pass} -e "use $database; SET foreign_key_checks = 0; ALTER TABLE ${table} IMPORT TABLESPACE; flush privileges;"
done
 
exit 0
해보진 않아서 모름

복구 완료

근데 상세페이지로 가면 404 에러가 뜬다.( 망할 )

어드민에서  해당 글마다 post url 로 맵핑된 곳이 깨진듯 해서 일일히 새로 post url 을 다시 저장하니 상세페이지도 연결이 잘 되었다.
( 기존 post url 그대로 저장하면 안되고 한글 1글자 추가 -> 저장 -> 1글자 다시 빼기 -> 저장 식으로 해야 먹혔다 )

Subscribe to X세대 신입사원

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe
774-86-01972 cinnabar.3d@gmail.com