MySQL 완벽 가이드

MySQL은 가장 널리 사용되는 오픈소스 관계형 데이터베이스입니다. 이 가이드에서는 설치부터 실무에서 자주 사용하는 모든 SQL 문법을 다룹니다.

설치

Ubuntu/Linux

sudo apt-get update
sudo apt-get install mysql-server
mysql_secure_installation    # 보안 설정
systemctl status mysql.service   # 실행 상태 확인
sudo systemctl start mysql   # MySQL 시작

macOS

brew install mysql
mysql.server start
mysql -u root

비밀번호 설정

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';

접속 및 기본 설정

MySQL 접속

mysql -u username -p

외부 접속 허용 계정 생성

-- 계정 생성
CREATE USER 'username'@'%' IDENTIFIED BY 'password';

-- 모든 권한 부여
GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'%' WITH GRANT OPTION;

-- 권한 적용
FLUSH PRIVILEGES;

외부 접속 설정 (Ubuntu)

# 설정 파일 수정
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

# bind-address = 127.0.0.1 주석 처리 후 재시작
sudo /etc/init.d/mysql restart

데이터베이스 관리

데이터베이스 생성/삭제

-- 생성
CREATE DATABASE db_name;
CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 삭제
DROP DATABASE db_name;

-- 목록 조회
SHOW DATABASES;

-- 선택
USE db_name;

테이블 관리

테이블 생성

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE,
    age INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

테이블 복사

-- 구조만 복사 (AUTO_INCREMENT, INDEX 포함)
CREATE TABLE new_table LIKE old_table;

-- 구조와 데이터 복사 (AUTO_INCREMENT 미포함)
CREATE TABLE new_table SELECT * FROM old_table;

-- 데이터만 복사
INSERT INTO new_table SELECT * FROM old_table;

-- 특정 컬럼만 복사
INSERT INTO new_table(col1, col2) SELECT col1, col2 FROM old_table;

테이블 조회

SHOW TABLES;
DESCRIBE table_name;
SHOW CREATE TABLE table_name;

INSERT (데이터 삽입)

기본 구문

-- 단일 행 삽입
INSERT INTO users (name, email, age) VALUES ('홍길동', 'hong@example.com', 25);

-- 다중 행 삽입
INSERT INTO users (name, email, age) VALUES
    ('김철수', 'kim@example.com', 30),
    ('이영희', 'lee@example.com', 28),
    ('박민수', 'park@example.com', 35);

중복 키 처리

-- 중복 시 업데이트 (UPSERT)
INSERT INTO users (id, name, email) VALUES (1, '홍길동', 'hong@example.com')
ON DUPLICATE KEY UPDATE
    name = VALUES(name),
    email = VALUES(email);

-- 중복 시 무시
INSERT IGNORE INTO users (name, email) VALUES ('홍길동', 'hong@example.com');

AUTO_INCREMENT 관리

-- AUTO_INCREMENT 시작값 변경
ALTER TABLE users AUTO_INCREMENT = 100;

-- AUTO_INCREMENT 초기화
ALTER TABLE users AUTO_INCREMENT = 0;

SELECT (데이터 조회)

기본 구문

-- 전체 조회
SELECT * FROM users;

-- 특정 컬럼 조회
SELECT name, email FROM users;

-- 조건 조회
SELECT * FROM users WHERE age > 25;

-- 정렬
SELECT * FROM users ORDER BY created_at DESC;

-- 제한
SELECT * FROM users LIMIT 10;
SELECT * FROM users LIMIT 10 OFFSET 20;  -- 페이지네이션

조건문

-- AND, OR
SELECT * FROM users WHERE age > 25 AND name LIKE '김%';

-- IN
SELECT * FROM users WHERE id IN (1, 2, 3);

-- BETWEEN
SELECT * FROM users WHERE age BETWEEN 20 AND 30;

-- IS NULL / IS NOT NULL
SELECT * FROM users WHERE email IS NOT NULL;

-- LIKE 패턴 매칭
SELECT * FROM users WHERE name LIKE '김%';     -- '김'으로 시작
SELECT * FROM users WHERE name LIKE '%수';     -- '수'로 끝남
SELECT * FROM users WHERE name LIKE '%길%';    -- '길' 포함

집계 함수

SELECT COUNT(*) FROM users;
SELECT AVG(age) FROM users;
SELECT MAX(age), MIN(age) FROM users;
SELECT SUM(age) FROM users;

-- GROUP BY
SELECT age, COUNT(*) as count FROM users GROUP BY age;

-- HAVING (그룹 조건)
SELECT age, COUNT(*) as count FROM users GROUP BY age HAVING count > 5;

JOIN

-- INNER JOIN
SELECT u.name, o.order_date
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- LEFT JOIN
SELECT u.name, o.order_date
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- RIGHT JOIN
SELECT u.name, o.order_date
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;

UPDATE (데이터 수정)

기본 구문

UPDATE users SET name = '새이름' WHERE id = 1;

-- 여러 컬럼 수정
UPDATE users SET name = '새이름', age = 30 WHERE id = 1;

값 증가/감소

-- 특정 값 증가
UPDATE users SET login_count = login_count + 1 WHERE id = 1;

-- 특정 값 감소
UPDATE products SET stock = stock - 1 WHERE id = 100;

조건부 업데이트

UPDATE users
SET status = CASE
    WHEN age < 20 THEN 'minor'
    WHEN age >= 20 AND age < 65 THEN 'adult'
    ELSE 'senior'
END;

DELETE (데이터 삭제)

기본 구문

-- 조건 삭제
DELETE FROM users WHERE id = 1;

-- 여러 조건
DELETE FROM users WHERE age < 18 AND status = 'inactive';

-- 전체 삭제 (주의!)
DELETE FROM users;

-- 테이블 비우기 (더 빠름, AUTO_INCREMENT 초기화)
TRUNCATE TABLE users;

안전한 삭제

-- 삭제 전 확인
SELECT * FROM users WHERE status = 'inactive';

-- 확인 후 삭제
DELETE FROM users WHERE status = 'inactive';

ALTER (테이블 구조 변경)

컬럼 추가/수정/삭제

-- 컬럼 추가
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
ALTER TABLE users ADD COLUMN address VARCHAR(255) AFTER email;

-- 컬럼 타입 변경
ALTER TABLE users MODIFY COLUMN age BIGINT;

-- 컬럼명 및 타입 변경
ALTER TABLE users CHANGE COLUMN old_name new_name VARCHAR(100);

-- 컬럼 삭제
ALTER TABLE users DROP COLUMN phone;

제약조건

-- PRIMARY KEY 추가
ALTER TABLE users ADD PRIMARY KEY (id);

-- UNIQUE 제약조건 추가
ALTER TABLE users ADD UNIQUE (email);

-- FOREIGN KEY 추가
ALTER TABLE orders ADD FOREIGN KEY (user_id) REFERENCES users(id);

-- 제약조건 삭제
ALTER TABLE users DROP INDEX email;

INDEX (인덱스)

인덱스는 검색 성능을 향상시키지만, INSERT/UPDATE/DELETE 성능에는 영향을 줄 수 있습니다.

인덱스 생성

-- 단일 컬럼 인덱스
CREATE INDEX idx_name ON users(name);

-- 복합 인덱스
CREATE INDEX idx_name_email ON users(name, email);

-- UNIQUE 인덱스
CREATE UNIQUE INDEX idx_email ON users(email);

인덱스 조회

SHOW INDEX FROM users;

인덱스 삭제

DROP INDEX idx_name ON users;

인덱스 사용 팁

  • WHERE, JOIN, ORDER BY에 자주 사용되는 컬럼에 인덱스 생성
  • 카디널리티(고유값 비율)가 높은 컬럼에 효과적
  • 복합 인덱스는 왼쪽부터 순서대로 사용됨

mysqladmin 명령어

MySQL 콘솔 외부에서 관리 작업을 수행할 수 있습니다.

# 데이터베이스 생성
mysqladmin -u root -p create db_name

# 데이터베이스 삭제
mysqladmin -u root -p drop db_name

# MySQL 상태 확인
mysqladmin -u root -p status

# MySQL 버전 확인
mysqladmin -u root -p version

# SQL 문 실행
mysqladmin -u root -p -e "SHOW DATABASES"

유용한 팁

대량 데이터 삽입 최적화

-- 트랜잭션으로 묶어서 삽입
START TRANSACTION;
INSERT INTO users (name) VALUES ('user1');
INSERT INTO users (name) VALUES ('user2');
-- ... 많은 INSERT
COMMIT;

쿼리 실행 계획 확인

EXPLAIN SELECT * FROM users WHERE name = '홍길동';

테이블 최적화

OPTIMIZE TABLE users;
ANALYZE TABLE users;