Files
llm-wiki/raw/official-docs/skip-locked-mysql-docs.md

118 lines
11 KiB
Markdown

---
title: MySQL 8.0 InnoDB Locking Reads — NOWAIT and SKIP LOCKED (공식 문서)
source_type: official-doc
url: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
archive_url:
status: raw
confidence: high
tags: [official-doc, ca-outbox-pattern, skip-locked, mysql, persistence, messaging, outbox-pattern]
related_branches: [feature-domain-event-outbox-contract]
related_projects: [ca-skeleton-operational-contract]
vendor: Oracle / MySQL
created: 2026-06-11
last_reviewed: 2026-06-11
---
# MySQL 8.0 InnoDB Locking Reads — NOWAIT and SKIP LOCKED (공식 문서)
> Layer: `raw/official-docs/` — MySQL 8.0 Reference Manual, §InnoDB Locking Reads 의 **원문 발췌·출처 기록**.
> D4 의 MySQL 측 일반화 근거 — PostgreSQL 공식(`skip-locked-postgres-docs`)의 SKIP LOCKED 설명이 MySQL 8.0+ 공식 문서와 시맨틱·경고 문구·use-case 에서 일치하는지 대조하기 위한 archive.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-domain-event-outbox-contract]] | D4 — "outbox publisher leadership = DB row-level SKIP LOCKED claim (PostgreSQL FOR UPDATE SKIP LOCKED / MySQL 8.0+ SKIP LOCKED)" 의 MySQL 측 일반화 — PostgreSQL 한정 인용(`SK-PG-C1`, `SK-PG-C2`)을 MySQL 8.0+ 공식 시맨틱으로 보완 |
## 출처 / Source
- 원본 URL: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
- 아카이브 URL: (미수집)
- 저자 / 조직: Oracle Corporation / MySQL Documentation Team
- 발행일: MySQL 8.0 Reference Manual (rolling — 8.0 계열)
- 마지막 확인일: 2026-06-11
## 왜 저장했는지 / Why archived
feature-domain-event-outbox-contract D4 는 outbox publisher 의 row claim 메커니즘을 "PostgreSQL FOR UPDATE SKIP LOCKED / MySQL 8.0+ SKIP LOCKED" 로 명시하지만, 근거 raw 는 PostgreSQL 공식(`skip-locked-postgres-docs`) 에만 있었다. D4 의 MySQL 8.0+ 일반화 주장을 MySQL 공식 문서로 보강해 `SK-PG-C1`/`SK-PG-C2` 와 동등한 MySQL 공식 claim 을 확보한다. 특히 "inconsistent view" 경고 문구와 queue-like table use-case 가 양 벤더 문서에서 동일하게 등장하는지 대조하는 것이 이 archive 의 핵심 목적이다.
## 핵심 인용 / Key quotes (verbatim, 3~5문장)
> [§Locking Read Concurrency with NOWAIT and SKIP LOCKED — SKIP LOCKED behavior] "A locking read that uses `SKIP LOCKED` never waits to acquire a row lock. The query executes immediately, removing locked rows from the result set."
> [§Locking Read Concurrency with NOWAIT and SKIP LOCKED — Note (inconsistent view warning)] "Queries that skip locked rows return an inconsistent view of the data. `SKIP LOCKED` is therefore not suitable for general transactional work. However, it may be used to avoid lock contention when multiple sessions access the same queue-like table."
> [§Locking Read Concurrency with NOWAIT and SKIP LOCKED — NOWAIT behavior] "A locking read that uses `NOWAIT` never waits to acquire a row lock. The query executes immediately, failing with an error if a requested row is locked."
> [§Locking Read Concurrency with NOWAIT and SKIP LOCKED — replication constraint] "Statements that use `NOWAIT` or `SKIP LOCKED` are unsafe for statement based replication."
## Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| SK-MYSQL-C1 | MySQL 에서 `SELECT ... FOR UPDATE SKIP LOCKED` (또는 `FOR SHARE SKIP LOCKED`) 는 row lock 을 즉시 획득할 수 없는 row 를 **결과 집합에서 제거**한다 (대기하지 않음) | [§NOWAIT and SKIP LOCKED — SKIP LOCKED behavior] "A locking read that uses `SKIP LOCKED` never waits to acquire a row lock. The query executes immediately, removing locked rows from the result set." | `official-vendor-doc` | MySQL 8.0 InnoDB, `SELECT ... FOR UPDATE SKIP LOCKED``SELECT ... FOR SHARE SKIP LOCKED` | "제거된 row 가 영원히 누락된다"는 뜻은 아님 — 다음 polling 에서 다시 후보가 됨. PostgreSQL 과 동일 보장이라는 뜻도 아님(구현은 벤더별 독립) |
| SK-MYSQL-C2 | SKIP LOCKED 를 사용하는 쿼리는 **데이터의 inconsistent view 를 반환**하므로 일반 트랜잭션 작업에는 적합하지 않으며, **여러 세션이 동일 queue-like table 에 접근할 때 lock contention 을 피하는 용도**로 사용할 수 있다 | [§NOWAIT and SKIP LOCKED — Note] "Queries that skip locked rows return an inconsistent view of the data. `SKIP LOCKED` is therefore not suitable for general transactional work. However, it may be used to avoid lock contention when multiple sessions access the same queue-like table." | `official-vendor-doc` | MySQL 8.0 InnoDB SKIP LOCKED 의 적용 영역 — queue / outbox / job table 패턴 | "queue-like table 에서는 무조건 SKIP LOCKED 가 best practice" 라는 일반화는 본 인용에 없음 — 단지 contention 회피 도구로 적합하다는 명시 |
| SK-MYSQL-C3 | MySQL 에서 `NOWAIT` 는 lock 을 즉시 획득할 수 없으면 **대기 없이 즉시 에러로 실패**한다 | [§NOWAIT and SKIP LOCKED — NOWAIT behavior] "A locking read that uses `NOWAIT` never waits to acquire a row lock. The query executes immediately, failing with an error if a requested row is locked." | `official-vendor-doc` | MySQL 8.0 InnoDB `SELECT ... FOR UPDATE NOWAIT` | SKIP LOCKED 와 NOWAIT 의 차이 (에러 vs skip) 는 본 인용에 직접 비교 없음 — 각 단독 기술만 있음 |
| SK-MYSQL-C4 | `NOWAIT` 또는 `SKIP LOCKED` 를 사용하는 구문은 **statement-based replication 에서 안전하지 않다** | [§Locking Read Concurrency with NOWAIT and SKIP LOCKED — replication constraint] "Statements that use `NOWAIT` or `SKIP LOCKED` are unsafe for statement based replication." | `official-vendor-doc` | MySQL 8.0 statement-based replication (SBR) 환경 | row-based replication (RBR) 또는 GTID replication 에서의 안전성은 별도 확인 필요 |
### Strength 정책
- `SK-MYSQL-C1` ~ `SK-MYSQL-C4`: 2026-06-11 WebFetch verbatim 확인 성공 → `official-vendor-doc`
## Usage Boundaries / 적용 경계
### 이 자료가 직접 증명하는 것
- `SK-MYSQL-C1`: MySQL 8.0 에서 SKIP LOCKED 의 정확한 동작 — 즉시 실행, locked row 는 결과 집합에서 제거
- `SK-MYSQL-C2`: MySQL 8.0 공식 문서가 SKIP LOCKED 의 queue-like table use-case 를 명시적으로 인정
- `SK-MYSQL-C3`: MySQL 8.0 에서 NOWAIT 의 동작 (fail-fast)
- `SK-MYSQL-C4`: statement-based replication 환경에서의 안전성 제약
### PostgreSQL 공식(`skip-locked-postgres-docs`) 과의 시맨틱 대조
> 이 archive 의 핵심 목적 — MySQL vs PostgreSQL 공식 wording 비교.
| 항목 | PostgreSQL (`SK-PG-C1`, `SK-PG-C2`) | MySQL (`SK-MYSQL-C1`, `SK-MYSQL-C2`) | 일치 여부 |
|---|---|---|---|
| **SKIP LOCKED 동작** | "any selected rows that cannot be immediately locked are skipped" | "removing locked rows from the result set" | **의미 일치** — "skip" vs "removing from result set" 은 동일 시맨틱의 다른 표현 |
| **inconsistent view 경고** | "Skipping locked rows provides an inconsistent view of the data" | "Queries that skip locked rows return an inconsistent view of the data" | **문구 거의 동일** — 핵심 경고 wording 이 양 벤더 공식에 동일하게 등장 |
| **일반 목적 부적합** | "not suitable for general purpose work" | "not suitable for general transactional work" | **의미 동일** — "general purpose work" vs "general transactional work" |
| **queue-like table use-case** | "can be used to avoid lock contention with multiple consumers accessing a queue-like table" | "may be used to avoid lock contention when multiple sessions access the same queue-like table" | **문구 거의 동일** — "consumers" vs "sessions", "a" vs "the same" 의 표현 차이만 있고 의미는 동일 |
| **lock 대기 없음** | (별도 섹션에서 "immediately") | "never waits to acquire a row lock. The query executes immediately" | **의미 일치** |
**결론**: MySQL 8.0 공식 문서의 SKIP LOCKED 시맨틱·경고·use-case 는 PostgreSQL 공식 문서와 **실질적으로 동일하다**. D4 의 "PostgreSQL FOR UPDATE SKIP LOCKED / MySQL 8.0+ SKIP LOCKED" 일반화는 두 벤더의 공식 문서 모두로 지지된다.
### 이 자료가 증명하지 않는 것
- MySQL 과 PostgreSQL 의 InnoDB/Postgres lock manager 내부 구현이 동일하다는 것 (각 벤더 독립 구현)
- MySQL 버전별 도입 시점 (본 페이지는 MySQL 8.0 Reference Manual 전반을 대상 — 특정 도입 마이너 버전 미명시)
- statement-based replication 외 다른 replication 방식 (RBR, GTID) 에서의 안전성
- outbox polling 의 정확한 throughput / interval / batch size 최적값
- MySQL 의 SKIP LOCKED 가 autocommit 비활성화 없이 동작하는가 (페이지 본문: locking reads require autocommit disabled)
### 내 프로젝트에 적용하려면 추가 확인이 필요한 것
- ca-tmpl 의 outbox publisher 가 MySQL 환경에서 `FOR UPDATE SKIP LOCKED` 를 사용하는 경우 실제 row-based replication 설정이 되어 있는지 확인 (statement-based replication 제약, `SK-MYSQL-C4`)
- MySQL 버전 — ca-tmpl 타깃이 MySQL 8.0 이상인지 확인 (8.0 이전은 SKIP LOCKED 지원 없음)
- PostgreSQL primary + MySQL fallback 지원 구조라면 dialect-specific query 분기 필요
## 메모 / Notes
- 핵심 발견: MySQL 8.0 공식 문서가 PostgreSQL 공식과 사실상 동일한 "inconsistent view" 경고 + "queue-like table" use-case 문구를 사용한다. D4 의 MySQL 일반화가 공식 근거로 뒷받침됨.
- NOWAIT (C3): SKIP LOCKED 와 동일 섹션에서 소개되지만 의미가 다름 — NOWAIT 는 에러, SKIP LOCKED 는 skip. outbox polling 에서는 SKIP LOCKED 가 맞는 선택.
- replication 제약 (C4): statement-based replication 환경에서 SKIP LOCKED 쿼리가 unsafe 로 분류됨 — 운영 DB 의 replication 방식이 SBR 이면 주의 필요.
- 버전: 본 페이지는 MySQL 8.0 Reference Manual — SKIP LOCKED 는 8.0 계열 문서에서만 등장 (5.7 이하 미지원 추정).
- 추가로 봐야 할 동일 출처 페이지: `https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html` (InnoDB Locking 개요)
## Related / 관련
- 같은 주제 다른 official-doc (Postgres 대응본):
- [[raw/official-docs/skip-locked-postgres-docs]] — PostgreSQL FOR UPDATE SKIP LOCKED 공식 문서 (시맨틱 대조 대상)
- 같은 주제 다른 공식 자료:
- [[raw/official-docs/outbox-skip-locked-microservices-io]] — Chris Richardson outbox pattern 원형 (queue polling use-case 정의)
- [[raw/official-docs/outbox-debezium-official-docs]] — 대안 1: Debezium CDC
- [[raw/official-docs/dual-write-antipattern-microservices-io]] — negative reference
- 이 자료를 인용하는 branch / project:
- [[raw/branch-notes/feature-domain-event-outbox-contract]]
- 인용한 wiki 요약: (미작성)