사실 MySQL의 경우, 기본키를 설정하지 않아도 테이블이 만들어집니다. 어떻게 이게 가능한 걸까요?

MySQL이 기본키가 없어도 내부적으로 숨겨진 클러스터드 인덱스(Hidden Clustered Index) 를 자동 생성하기 때문입니다.

InnoDB의 기본키 결정 순서

1순위: 사용자가 명시한 PRIMARY KEY
        ↓ 없으면
2순위: NOT NULL + UNIQUE 컬럼 중 첫 번째
        ↓ 없으면
3순위: 내부적으로 숨겨진 6바이트 RowID 자동 생성 (GEN_CLUST_INDEX)

GEN_CLUST_INDEX란?

-- 기본키 없이 테이블 생성
CREATE TABLE no_pk (
    name VARCHAR(100),
    email VARCHAR(100)
);

-- 사용자 눈에는 보이지 않지만 내부적으로 아래와 같이 동작
-- ROW_ID (6byte, 전역 카운터) 가 숨겨진 PK 역할
┌──────────────────────────────────┐
│  숨겨진 ROW_ID  │  name  │  email │
│  (6byte)        │        │        │
├─────────────────┼────────┼────────┤
│  000001         │  kim   │  a@..  │
│  000002         │  lee   │  b@..  │
└──────────────────────────────────┘

명시적 PK가 없을 때의 문제점

문제설명
ROW_ID 전역 공유모든 PK 없는 테이블이 하나의 카운터 공유 → 경합 발생
복제 위험ROW_ID는 복제(Replication) 시 전달되지 않아 Row 식별 불가
성능 저하외부에서 ROW_ID 접근 불가 → 인덱스 활용 어려움
파티셔닝 불가PK 없으면 파티셔닝 설정 불가

확인 방법

-- 실제 인덱스 확인
SHOW INDEX FROM no_pk;
-- 결과: 아무것도 안 나옴 (숨겨진 인덱스는 노출 안 됨)

-- InnoDB 내부 상태 확인
SELECT * FROM information_schema.INNODB_INDEXES
WHERE NAME = 'GEN_CLUST_INDEX';

결론

MySQL이 PK 없이도 테이블을 만들 수 있는 건 InnoDB가 자동으로 숨겨진 키를 만들어주기 때문입니다. 하지만 이는 성능/복제/안정성 측면에서 문제가 생기므로, 항상 명시적 기본키를 선언하는 것이 원칙입니다.

CSLOG에서 보기