MariaDB errno: 13 Permission denied 해결 과정
워드프레스나 다른 웹 애플리케이션을 운영하다가 MariaDB(또는 MySQL) 로그에서 아래와 같은 오류를 본 적이 있으신가요?
[ERROR] InnoDB: Operating system error number 13 in a file operation.
[ERROR] InnoDB: Error number 13 means 'Permission denied'
[ERROR] InnoDB: File .../ibdata1: 'open' returned OS error 213
또는 서비스가 아예 시작되지 않고 곧바로 종료되는 경우도 있습니다. 이번 글에서는 MariaDB errno: 13 (Permission denied) 오류가 왜 발생하는지, 그리고 실제로 어떻게 해결했는지 과정을 단계별로 정리했습니다.
1. errno 13이 의미하는 것
리눅스 시스템에서 errno 13은 표준 시스템 오류 코드로 “Permission denied”, 즉 권한 부족을 의미합니다. MariaDB/MySQL이 데이터 디렉터리(/var/lib/mysql 등)의 파일을 읽거나 쓰려고 시도했지만, 현재 프로세스를 실행 중인 사용자(보통 mysql)가 해당 파일/폴더에 대한 접근 권한이 없을 때 발생합니다.
즉, MariaDB 자체의 버그가 아니라 파일 시스템 권한 설정 문제인 경우가 대부분입니다.
2. 오류 발생 상황 재현
상황 1: Docker 컨테이너 재생성 후 발생
docker compose down
docker compose up -d
컨테이너를 내렸다 다시 올렸을 뿐인데 DB 컨테이너가 계속 재시작(restart loop)되며 로그에 errno 13이 찍히는 경우가 흔합니다.
상황 2: 서버 마이그레이션 후 발생
기존 서버의 /var/lib/mysql 디렉터리를 통째로 새 서버로 복사(rsync, scp 등)한 뒤 MariaDB를 시작하면 소유권이 이전 서버의 UID/GID 그대로 남아 있어 오류가 발생합니다.
상황 3: SELinux가 활성화된 CentOS/RHEL 계열
권한(755, 644 등)은 맞는데도 SELinux 컨텍스트가 맞지 않아 접근이 차단되는 경우입니다.
3. 해결 과정 1단계: 로그로 정확한 원인 파악하기
먼저 정확히 어떤 파일에서 오류가 나는지 로그를 확인합니다.
호스트에 직접 설치한 경우:
sudo tail -n 50 /var/log/mysql/error.log
Docker 컨테이너의 경우:
docker logs wordpress_db --tail 50
로그에서 ibdata1, ib_logfile0처럼 구체적인 파일명이 언급되면, 그 파일이 있는 디렉터리 전체의 권한을 점검해야 합니다.
4. 해결 과정 2단계: 소유권(Ownership) 확인 및 수정
호스트에 직접 설치한 MariaDB의 경우
# 현재 소유권 확인
ls -la /var/lib/mysql
# mysql 사용자/그룹으로 소유권 재설정
sudo chown -R mysql:mysql /var/lib/mysql
# 권한 재설정 (디렉터리 750, 파일 660 권장)
sudo find /var/lib/mysql -type d -exec chmod 750 {} \;
sudo find /var/lib/mysql -type f -exec chmod 660 {} \;
# 서비스 재시작
sudo systemctl restart mariadb
Docker Compose 환경의 경우
Docker에서는 대부분 볼륨 마운트 방식이 원인입니다. docker-compose.yml을 다음과 같이 점검하세요.
services:
db:
image: mariadb:10.11
container_name: wordpress_db
restart: always
environment:
MARIADB_ROOT_PASSWORD: rootpassword
MARIADB_DATABASE: wordpress
MARIADB_USER: wordpress
MARIADB_PASSWORD: wordpresspassword
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
named volume(db_data)를 사용 중이라면 Docker가 자동으로 권한을 관리하므로 문제가 드뭅니다. 반면 **bind mount(호스트 폴더 직접 연결)**를 사용 중이라면 아래처럼 호스트 폴더 권한을 명시적으로 맞춰야 합니다.
volumes:
- ./mysql-data:/var/lib/mysql
# MariaDB 컨테이너 내부 mysql 사용자의 UID 확인 (보통 999)
docker exec -it wordpress_db id mysql
# 호스트 폴더 소유권을 해당 UID로 맞추기
sudo chown -R 999:999 ./mysql-data
5. 해결 과정 3단계: SELinux 컨텍스트 문제 해결 (CentOS/RHEL 계열)
chown, chmod를 모두 정상적으로 맞췄는데도 오류가 계속된다면 SELinux를 의심해야 합니다.
# SELinux 활성화 여부 확인
getenforce
# 현재 컨텍스트 확인
ls -Z /var/lib/mysql
컨텍스트가 mysqld_db_t가 아니라면 아래 명령으로 복구합니다.
sudo restorecon -Rv /var/lib/mysql
Docker를 사용 중이고 SELinux가 원인이라면, 볼륨 마운트 시 :z 또는 :Z 옵션을 추가하는 방법도 있습니다.
volumes:
- ./mysql-data:/var/lib/mysql:z
6. 해결 과정 4단계: 잘못된 소유권으로 이미 손상된 경우
권한만 고쳤는데도 MariaDB가 여전히 시작되지 않는다면, InnoDB 로그 파일이 이전 권한 상태에서 이미 손상되었을 가능성이 있습니다. 이 경우 아래 순서로 접근합니다.
- 반드시 먼저 백업:
/var/lib/mysql전체를 다른 곳에 복사해두세요. ib_logfile0,ib_logfile1등 로그 파일만 삭제 후 재시작 시도 (데이터 파일ibdata1은 유지)- 그래도 안 되면
mysqldump로 덤프를 뜰 수 있는지 확인 후, 새 데이터 디렉터리로 재구축
# 예시: 손상 의심되는 로그 파일만 백업 후 제거
sudo mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bak
sudo mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bak
sudo systemctl restart mariadb
이 단계는 데이터 손실 위험이 있으므로, 반드시 백업을 먼저 진행한 뒤 시도하세요.
7. 원인별 해결 방법 요약
| 원인 | 해결 방법 |
|---|---|
| 소유권이 mysql 사용자가 아님 | chown -R mysql:mysql /var/lib/mysql |
| 권한 값이 지나치게 제한적이거나 느슨함 | 디렉터리 750, 파일 660으로 재설정 |
| 서버 마이그레이션 후 UID 불일치 | 새 서버의 mysql UID/GID로 재설정 |
| Docker bind mount 소유권 불일치 | 컨테이너 내부 mysql UID로 호스트 폴더 chown |
| SELinux 컨텍스트 문제 | restorecon -Rv 또는 볼륨에 :z 옵션 추가 |
| 파일 자체 손상 | 백업 후 로그 파일 제거, 최악의 경우 덤프로 재구축 |
8. 재발 방지를 위한 팁
- 서버 마이그레이션이나 백업 복원 시 rsync에
-a옵션을 사용해 소유권/권한을 그대로 유지하세요. 그렇지 않으면 실행 계정 권한으로 파일이 생성되어 문제가 반복됩니다. - Docker 환경이라면 가능한 한 named volume을 사용하는 것이 권한 문제를 원천적으로 줄이는 방법입니다. bind mount는 편리하지만 권한 관리를 직접 해줘야 합니다.
- 운영 서버에서는 정기적으로
mysqldump기반 백업을 별도로 유지해, 파일 손상 시에도 빠르게 복구할 수 있도록 대비하세요.
마무리
MariaDB의 errno: 13 오류는 대부분 파일 시스템 권한 문제로 귀결됩니다. 로그에서 정확한 파일 경로를 확인하고, 소유권과 권한을 mysql 실행 계정에 맞게 재설정하면 대부분 해결됩니다. Docker 환경이라면 bind mount의 UID 불일치를, SELinux 환경이라면 컨텍스트 문제를 우선적으로 점검해보시기 바랍니다.