Foreign Key

μ™Έλž˜ν‚€

MySQLμ—μ„œ μ™Έλž˜ν‚€λŠ” InnoDB μŠ€ν† λ¦¬μ§€ μ—”μ§„μ—μ„œλ§Œ 생성할 수 있고, μ™Έλž˜ ν‚€ μ œμ•½μ΄ μ„€μ •λ˜λ©΄ μžλ™μœΌλ‘œ μ—°κ΄€λœ ν…Œμ΄λΈ”μ˜ μ»¬λŸΌμ— μΈλ±μŠ€κΉŒμ§€ μƒμ„±λœλ‹€. μ™Έλž˜ ν‚€κ°€ μ œκ±°λ˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ μžλ™μœΌλ‘œ μƒμ„±λœ 인덱슀λ₯Ό μ‚­μ œν•  수 μ—†λ‹€.

DB 잠금 λ©”μ»€λ‹ˆμ¦˜μ—μ„œ, μ™Έλž˜ν‚€μ˜ μ€‘μš”ν•œ 두 κ°€μ§€ νŠΉμ§•μ΄ μžˆλ‹€.

  1. ν…Œμ΄λΈ”μ˜ λ³€κ²½(μ“°κΈ° 잠금)이 λ°œμƒν•˜λŠ” κ²½μš°μ—λ§Œ 잠금 κ²½ν•©(잠금 λŒ€κΈ°)이 λ°œμƒν•œλ‹€.

    • 데이터λ₯Ό μˆ˜μ •ν•˜λŠ” μž‘μ—…(INSERT, UPDATE, DELETE)을 μˆ˜ν–‰ν•  λ•Œλ§Œ 잠금 경합이 μΌμ–΄λ‚œλ‹€.

    • λ‹¨μˆœνžˆ μ½λŠ” μž‘μ—…μœΌλ‘œλŠ” 잠금 경합이 λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

  2. μ™Έλž˜ 킀와 μ—°κ΄€λ˜μ§€ μ•Šμ€ 컬럼의 변경은 μ΅œλŒ€ν•œ 잠금 κ²½ν•©(잠금 λŒ€κΈ°)을 λ°œμƒμ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.

    • μ™Έλž˜ ν‚€λ‘œ μ—°κ²°λ˜μ§€ μ•Šμ€ μ»¬λŸΌμ„ λ³€κ²½ν•  λ•Œ, InnoDB 엔진이 κ°€λŠ₯ν•œ μž κΈˆμ„ μ΅œμ†Œν™”ν•˜μ—¬ λ™μ‹œμ„±μ„ ν–₯μƒμ‹œν‚€κΈ° μœ„ν•œ μ „λž΅μ΄λ‹€.

create table tb_parent (
	id int not null,
	fd varchar(100) not null, 
	primary key(id)
) ENGINE=InnoDB;

create table tb_child (
	id int not null,
	pid int default null, // parent.id 컬럼 참쑰
	fd varchar(100) default null,
	primary key (id),
	key ix_parent_id (pid),
	constraint child_ibfk_1 foreign key (pid) references tb_parent (id)
	on delete cascade
) ENGINE=InnoDB;

insert into tb_parent values (1, 'parent-1'), (2, 'parent-2');
insert into tb_child values (100, 1, 'child-100');

μœ„μ™€ ν…Œμ΄λΈ” 정보와 DML μΏΌλ¦¬μ—μ„œ, μ–Έμ œ μžμ‹ ν…Œμ΄λΈ”μ˜ 변경이 잠금 λŒ€κΈ°λ₯Ό ν•˜κ³ , μ–Έμ œ λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ 변경이 잠금 λŒ€κΈ°λ₯Ό ν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄μž.

μžμ‹ ν…Œμ΄λΈ”μ˜ 변경이 λŒ€κΈ°ν•˜λŠ” 경우

  1. 1번 컀λ„₯μ…˜μ—μ„œ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•˜κ³  λΆ€λͺ¨(tb_parent) ν…Œμ΄λΈ”μ—μ„œ id=2인 λ ˆμ½”λ“œμ— UPDATEλ₯Ό μ‹€ν–‰ν•œλ‹€.

    • 1번 컀λ„₯μ…˜μ΄ tb_parent ν…Œμ΄λΈ”μ—μ„œ id=2 λ ˆμ½”λ“œμ— μ“°κΈ° μž κΈˆμ„ νšλ“ν•œλ‹€.

  2. 2번 컀λ„₯μ…˜μ—μ„œ μžμ‹ ν…Œμ΄λΈ”(tb_child)의 μ™Έλž˜ ν‚€ 컬럼인 pidλ₯Ό 2둜 λ³€κ²½ν•˜λŠ” 쿼리λ₯Ό μ‹€ν–‰

    • 이 쿼리(μž‘μ—… 번호 4)λŠ” λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ λ³€κ²½ μž‘μ—…μ΄ μ™„λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦°λ‹€.

  3. λ‹€μ‹œ 1번 컀λ„₯μ…˜μ—μ„œ ROLLBACK, COMMIT으둜 νŠΈλžœμž­μ…˜μ„ μ’…λ£Œν•˜λ©΄ 2번 컀λ„₯μ…˜μ˜ λŒ€κΈ° μ€‘μ΄λ˜ μž‘μ—…μ΄ μ¦‰μ‹œ μ²˜λ¦¬λœλ‹€.

즉, μžμ‹ ν…Œμ΄λΈ”μ˜ μ™Έλž˜ ν‚€ 컬럼의 λ³€κ²½(insert, update)은 λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ 확인이 ν•„μš”ν•˜λ‹€. λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ ν•΄λ‹Ή λ ˆμ½”λ“œκ°€ μ“°κΈ° 잠금이 걸렀있으면 ν•΄λ‹Ή 잠금이 ν•΄μ œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ €μ•Ό ν•œλ‹€. 이것이 InnoDB μ™Έλž˜ ν‚€ κ΄€λ¦¬μ˜ 첫 번째 νŠΉμ§•μ΄λ‹€.

μ™Έλž˜ν‚€ μ œμ•½ 쑰건은 λ°μ΄ν„°μ˜ 일관성과 무결성을 μœ μ§€ν•˜κΈ° μœ„ν•΄ μ‘΄μž¬ν•œλ‹€. μžμ‹ ν…Œμ΄λΈ”μ˜ μž…μž₯μ—μ„œ 보면,

  • INSERT: μžμ‹ ν…Œμ΄λΈ”μ— μƒˆ λ ˆμ½”λ“œλ₯Ό μ‚½μž…ν•  λ•Œ, μ™Έλž˜ν‚€ 값이 λΆ€λͺ¨ ν…Œμ΄λΈ”μ— μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€.

  • UPDATE: μžμ‹ ν…Œμ΄λΈ”μ˜ μ™Έλž˜ν‚€ 값을 λ³€κ²½ν•  λ•Œ, μƒˆλ‘œμš΄ 값이 λΆ€λͺ¨ ν…Œμ΄λΈ”μ— μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.

  • DELETE: 일반적으둜 μžμ‹ ν…Œμ΄λΈ”μ˜ λ ˆμ½”λ“œ μ‚­μ œλŠ” λΆ€λͺ¨ ν…Œμ΄λΈ” 확인이 ν•„μš” μ—†μ§€λ§Œ, λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ λ ˆμ½”λ“œλ₯Ό μ‚­μ œν•˜λŠ” κ²½μš°μ—λŠ” μžμ‹ ν…Œμ΄λΈ”μ˜ μ°Έμ‘° μ—¬λΆ€λ₯Ό ν™•μΈν•œλ‹€.

λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ λ³€κ²½ μž‘μ—…μ΄ λŒ€κΈ°ν•˜λŠ” 경우

  1. 1번 컀λ„₯μ…˜μ—μ„œ λΆ€λͺ¨ ν‚€ β€˜1’을 μ°Έμ‘°ν•˜λŠ” μžμ‹ ν…Œμ΄λΈ”μ˜ λ ˆμ½”λ“œλ₯Ό λ³€κ²½ν•˜λ©΄ tb_child ν…Œμ΄λΈ”μ˜ λ ˆμ½”λ“œμ— λŒ€ν•΄ μ“°κΈ° μž κΈˆμ„ νšλ“ν•œλ‹€.

  2. 2번 컀λ„₯μ…˜μ΄ tb_parent ν…Œμ΄λΈ”μ—μ„œ id=1 인 λ ˆμ½”λ“œλ₯Ό μ‚­μ œν•œλ‹€.

    • 이 쿼리(μž‘μ—… 번호4)λŠ” tb_child ν…Œμ΄λΈ”μ˜ λ ˆμ½”λ“œμ— λŒ€ν•œ μ“°κΈ° 잠금이 ν•΄μ œλ  λ•ŒκΉŒμ§€ λŒ€κΈ°ν•œλ‹€.

    • μžμ‹ ν…Œμ΄λΈ”μ΄ 생성될 λ•Œ μ •μ˜λœ μ™Έλž˜ν‚€μ˜ νŠΉμ„±(cascade) λ•Œλ¬Έμ— λΆ€λͺ¨ λ ˆμ½”λ“œκ°€ μ‚­μ œλ˜λ©΄ μžμ‹ λ ˆμ½”λ“œλ„ λ™μ‹œμ— μ‚­μ œλœλ‹€.

μ™Έλž˜ν‚€ μ œμ•½ 쑰건이 DB λ™μ‹œμ„±κ³Ό μ„±λŠ₯에 영ν–₯을 λ―ΈμΉ  수 μžˆλ‹€. μœ„ μ˜ˆμ‹œλ“€μ²˜λŸΌ,

μžμ‹ ν…Œμ΄λΈ”μ˜ λ ˆμ½”λ“œλ₯Ό λ³€κ²½ν•˜λ©΄ λΆ€λͺ¨ ν…Œμ΄λΈ”μ˜ κ΄€λ ¨ λ ˆμ½”λ“œμ—λ„ 영ν–₯을 μ£Όλ©΄μ„œ μ™Έλž˜ν‚€λ‘œ μ—°κ²°λœ ν…Œμ΄λΈ” κ°„ 잠금이 ν™•μž₯λœλ‹€.

또, μ™Έλž˜ν‚€κ°€ 있으면 DBλŠ” μ°Έμ‘° 무결성을 μœ μ§€ν•˜κΈ° μœ„ν•΄ 좔가적인 검사λ₯Ό μ‹€μ‹œν•˜λŠ”λ°, 이 κ³Όμ •μ—μ„œ μ—°κ΄€λœ ν…Œμ΄λΈ”μ— 읽기 μž κΈˆμ„ 걸게 λœλ‹€.

λ”°λΌμ„œ DBμ—μ„œ μ™Έλž˜ ν‚€λ₯Ό 물리적으둜 μƒμ„±ν•˜λŠ” κ²½μš°μ—λŠ” trade-offλ₯Ό κ³ λ €ν•˜μ—¬ λͺ¨λΈλ§μ„ μ§„ν–‰ν•˜λŠ” 것이 μ’‹λ‹€.

Last updated