Ubuntu에서 MySQL 설치부터 계정 생성, 접속 확인, 백업까지 진행하는 실습 가이드입니다. 기존 문서의 MySQL 8.0.45라는 버전은 apt 설치만으로 보장되지 않습니다. 먼저 저장소의 설치 후보를 확인하세요. 아래 IP·DB 이름·비밀번호는 예시이며 실제 환경에 맞게 바꿔야 합니다.

목차
1. 설치 전 Ubuntu와 패키지 버전 확인
Ubuntu 기본 저장소와 Oracle MySQL APT 저장소는 패키지 출처가 다릅니다. 기존 DB가 있다면 먼저 버전·저장소·백업 상태를 확인하고, 신규 설치 절차로 덮어쓰지 마세요.
|
1 2 3 4 5 6 7 |
cat /etc/os-release sudo apt update apt-cache policy mysql-server apt-cache madison mysql-server dpkg -l 'mysql*' 'mariadb*' |
policy 출력의 Candidate가 설치 후보입니다. Ubuntu 버전과 보안 업데이트 상태에 따라 8.0.45 이외의 버전이나 다른 계열이 선택될 수 있습니다. 정확한 8.0.45 재현이 목적이면 해당 OS에 맞는 서버·클라이언트·의존 패키지의 제공 여부를 함께 확인해야 합니다. 저장소에 없는 버전을 설치할 수 있는 것처럼 특정 버전 명령을 복사하지 마세요.
Oracle 저장소를 사용할 경우 공식 APT 안내에서 지원 Ubuntu 릴리스와 선택 가능한 MySQL 계열을 먼저 확인합니다. 저장소 변경과 기존 서버 업그레이드는 별도 작업으로 계획합니다.
2. MySQL 설치와 서비스 확인
다음은 Ubuntu 저장소에 설치 후보가 확인된 신규 서버의 예시입니다. apt가 제시하는 설치·제거 목록을 확인한 뒤 진행합니다.
|
1 2 3 4 5 6 |
sudo apt install mysql-server sudo systemctl status mysql --no-pager mysql --version sudo mysql |
마지막 명령으로 MySQL 프롬프트에 접속되면 다음 SQL을 실행합니다. mysql –version은 클라이언트 버전이고 SELECT VERSION()은 접속한 서버 버전입니다.
|
1 2 3 4 5 6 7 |
SELECT VERSION(); SELECT @@hostname, @@port; SHOW VARIABLES LIKE 'character_set_server'; SHOW VARIABLES LIKE 'collation_server'; EXIT; |
Ubuntu 패키지의 root 계정이 소켓 인증을 사용하면 sudo mysql로 접속할 수 있습니다. 비밀번호 인증으로 설치한 환경은 mysql -u root -p를 사용합니다. 관리자 접속 방식을 바꾸기 전에 현재 인증 방식을 확인하세요.
3. 초기 보안 설정
|
1 2 3 |
sudo mysql_secure_installation |
질문은 설치 버전과 기존 설정에 따라 달라집니다. 다음 기준으로 선택합니다.
| 질문 | 설정 기준 |
|---|---|
| VALIDATE PASSWORD | 비밀번호 정책을 사용할지 선택. 운영 환경에서는 강한 비밀번호 정책 적용 권장 |
| Remove anonymous users | Y — 익명 사용자 제거 |
| Disallow root login remotely | Y — root 원격 로그인 제한 |
| Remove test database | Y — 불필요한 테스트 DB 제거 |
| Reload privilege tables | Y — 도구가 수행한 변경 반영 |
root 소켓 인증 환경에서는 일반적인 비밀번호 로그인과 동작이 다를 수 있습니다. 오류가 나면 출력 내용을 확인하고 인증 플러그인을 무조건 변경하지 마세요.
4. 데이터베이스와 전용 계정 생성
셸에서 sudo mysql로 접속한 후 실행합니다. 예시 비밀번호는 그대로 사용하지 말고 고유한 긴 비밀번호로 바꿉니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'CHANGE_TO_A_UNIQUE_LONG_PASSWORD!'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'localhost'; SHOW GRANTS FOR 'appuser'@'localhost'; |
위 권한은 일반적인 데이터 조회·입력·수정·삭제용입니다. 테이블 생성·스키마 변경은 포함하지 않습니다. 배포나 마이그레이션에 필요한 CREATE·ALTER·INDEX 등의 권한은 별도 계정으로 관리하거나 필요한 시점에 부여합니다.
CREATE USER와 GRANT는 즉시 반영되므로 별도 FLUSH PRIVILEGES가 필요하지 않습니다. 기존 문서의 잘린 FLUSH PRIVILEG 명령도 사용할 필요가 없습니다.
| 계정 표현 | 의미 |
|---|---|
| ‘appuser’@’localhost’ | DB 서버 내부 접속용 계정 |
| ‘appuser’@’10.0.0.21’ | 지정된 애플리케이션 서버에서 접속하는 별도 계정 |
| ‘appuser’@’%’ | 접속 호스트를 광범위하게 허용하므로 기본 예제로 사용하지 않음 |
같은 사용자 이름이어도 host가 다르면 별도 계정입니다. appdb.* 권한과 *.* 전체 DB 권한도 구분해야 합니다. WordPress 설치·플러그인 업데이트는 스키마 변경 권한이 필요할 수 있으므로 위 CRUD 계정을 그대로 적용하면 안 됩니다.
5. 원격 접속이 필요한 경우에만 설정
웹 애플리케이션과 DB가 같은 서버라면 로컬 접속을 유지하고 3306 포트를 외부에 열지 않아도 됩니다. 아래는 DB 서버 10.0.0.10, 애플리케이션 서버 10.0.0.21이라는 사설망 예시입니다.
5-1. MySQL 수신 주소 지정
|
1 2 3 4 |
sudo cp -a /etc/mysql/mysql.conf.d/mysqld.conf /etc/mysql/mysql.conf.d/mysqld.conf.bak sudo vi /etc/mysql/mysql.conf.d/mysqld.conf |
백업 파일이 이미 있으면 덮어쓰지 않도록 다른 이름으로 저장합니다. 해당 파일의 [mysqld] 항목 아래 기존 설정을 수정합니다. 같은 항목을 여러 곳에 중복 추가하지 않습니다.
|
1 2 3 4 5 |
[mysqld] bind-address = 10.0.0.10 mysqlx-bind-address = 127.0.0.1 |
10.0.0.10은 DB 서버가 실제 보유한 주소여야 합니다. bind-address를 주석 처리해 모든 인터페이스로 노출시키기보다 필요한 주소를 지정합니다. 일반 MySQL 연결은 3306을 사용하며 X Protocol의 33060 포트는 별도 기능입니다.
5-2. 원격 계정과 방화벽
DB 관리자 세션에서 애플리케이션 서버 IP에 한정된 계정을 만듭니다.
|
1 2 3 4 5 6 |
CREATE USER 'appuser'@'10.0.0.21' IDENTIFIED BY 'CHANGE_TO_ANOTHER_UNIQUE_PASSWORD!'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'10.0.0.21'; |
DB 서버의 셸에서 방화벽 상태를 확인합니다. UFW가 사용 중인 경우 아래 규칙으로 접속 원본을 제한합니다. 기존의 광범위한 허용 규칙이 있으면 이 규칙을 추가해도 그 규칙은 계속 적용됩니다.
|
1 2 3 4 5 6 7 8 |
sudo ufw status numbered sudo ufw allow from 10.0.0.21 to any port 3306 proto tcp sudo mysqld --validate-config sudo systemctl restart mysql sudo systemctl status mysql --no-pager sudo ss -ltnp | grep ':3306' |
설정 검증이 실패하면 재시작하지 말고 오류를 수정합니다. restart는 연결을 끊을 수 있으므로 운영 서버에서는 작업 시간을 정합니다. 클라우드 보안 그룹·외부 방화벽도 같은 IP 기준으로 확인해야 합니다.
신뢰할 수 없는 네트워크를 통과한다면 VPN 또는 TLS를 구성합니다. TLS는 클라이언트에서 CA와 서버 이름까지 검증하는 VERIFY_IDENTITY 방식으로 구성하고, 서버 인증서의 이름과 접속 호스트를 일치시켜야 합니다. 단순 포트 개방은 암호화를 설정하지 않습니다.
6. 접속 확인과 SQL 실습
로컬 계정은 DB 서버에서, 원격 계정은 허용한 애플리케이션 서버에서 테스트합니다. -p 뒤에 비밀번호를 붙이지 않고 입력 프롬프트에서 입력하세요.
|
1 2 3 4 5 6 7 |
# DB 서버 내부 mysql -u appuser -p appdb # 허용된 애플리케이션 서버에서 mysql -h 10.0.0.10 -P 3306 -u appuser -p appdb |
관리자가 appdb에 실습용 테이블을 먼저 생성합니다.
|
1 2 3 4 5 6 7 8 |
USE appdb; CREATE TABLE connection_test ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, message VARCHAR(100) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); |
그다음 appuser 세션에서 데이터 작업과 실제 권한 계정을 확인합니다.
|
1 2 3 4 5 6 7 8 |
SELECT USER(), CURRENT_USER(), DATABASE(); INSERT INTO connection_test (message) VALUES ('MySQL 연결 성공'); SELECT * FROM connection_test; UPDATE connection_test SET message = '수정 성공' WHERE id = 1; DELETE FROM connection_test WHERE id = 1; EXIT; |
7. 백업과 복원
다음은 로컬 root 소켓 인증이 가능한 서버에서 appdb의 논리 백업을 만드는 예시입니다. InnoDB 테이블을 전제로 하며 백업 중 DDL 변경을 피합니다. MyISAM 등 비트랜잭션 테이블에는 동일한 일관성이 보장되지 않습니다.
|
1 2 3 4 5 6 7 |
umask 077 sudo mysqldump --single-transaction --routines --triggers --events \ --no-tablespaces --set-gtid-purged=OFF appdb > appdb_backup.sql echo $? ls -lh appdb_backup.sql |
종료 코드 0과 오류 출력을 확인합니다. 파일이 있다는 것만으로 성공은 아닙니다. 위 덤프는 appdb 데이터와 객체의 백업이며 사용자·권한을 함께 백업하지 않습니다. GTID 기반 복제 구축용 백업은 별도 정책이 필요합니다.
먼저 별도의 테스트 DB로 복원합니다. 기존 appdb에 덮어쓰는 복원은 데이터가 교체될 수 있습니다.
|
1 2 3 4 5 |
sudo mysql -e "CREATE DATABASE appdb_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;" sudo mysql appdb_restore < appdb_backup.sql sudo mysql -e "SHOW TABLES FROM appdb_restore;" |
루틴·이벤트·뷰에 원본 DB 이름이나 DEFINER가 포함되어 있으면 별도 DB 복원 시 추가 조정이 필요합니다. 운영 복구 계획에는 복원 시험, 서버 외부 사본, 암호화와 보관 기간을 포함합니다.
8. 자주 발생하는 오류
| 증상 | 확인 방법 |
|---|---|
| ERROR 1045 Access denied | 비밀번호, 사용자@호스트 조합, 인증 방식 확인. 로컬과 원격 계정 구분 |
| ERROR 2002 / 2003 | MySQL 서비스, 소켓 또는 TCP 주소, bind-address, 방화벽 확인 |
| ERROR 1819 | 비밀번호 정책에 맞는 길이·문자 조합으로 변경 |
| 인증 플러그인 관련 오류 | 클라이언트 드라이버의 MySQL 버전 호환성과 TLS 설정 확인. 구형 인증으로 낮추기 전에 드라이버 갱신 검토 |
| Illegal mix of collations | 비교 대상 컬럼·문자열의 문자셋과 collation 확인. 테이블 전체 변경 전에 영향과 인덱스 검토 |
| 재시작 실패 | 설정 오타, 잘못된 수신 IP, 저장 공간, 파일 권한, 서비스 로그 확인 |
|
1 2 3 4 5 |
sudo journalctl -u mysql -n 100 --no-pager sudo tail -n 100 /var/log/mysql/error.log df -h |
로그 파일 위치는 설치 구성에 따라 다를 수 있습니다. 서비스가 정상인 경우 관리자 세션에서 다음 정보를 확인합니다.
|
1 2 3 4 5 6 7 |
SELECT user, host, plugin FROM mysql.user; SHOW VARIABLES LIKE 'bind_address'; SHOW VARIABLES LIKE 'port'; SHOW VARIABLES LIKE 'log_error'; SHOW GRANTS FOR 'appuser'@'localhost'; |
완료 확인
- 실제 서버 버전과 패키지 출처를 기록했는가?
- 서비스가 정상이고 애플리케이션 계정으로 접속되는가?
- 계정 권한이 필요한 DB에 한정되어 있는가?
- 원격 접속은 필요한 IP에서만 가능하도록 제한했는가?
- 백업을 별도 환경에 복원해 확인했는가?
공식 참고 문서
문서 수정: 2026년 10월 25일. 명령어는 문서용 예시이며 이 페이지 편집으로 서버 설정이 실행되지는 않습니다.
