๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“• Spring Framework/Spring Project

2022.06.02 ใ€ŒDB ๋™์‹œ์„ฑ ๋ฌธ์ œใ€

by GroovyArea 2022. 6. 2.
์ž๋ฐ” ๊ธฐ๋ฐ˜ ์›น ํ”„๋กœ๊ทธ๋žจ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋™์‹œ์„ฑ ๊ด€๋ จ ๋ฌธ์ œ๋ฅผ ์ž˜ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋“ค์—ˆ๋‹ค. 
์ด๋ฒˆ์— ๋‚ด๊ฐ€ ํ•˜๋Š” ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ์—์„œ๋„ ๊ทธ ์ด์Šˆ๊ฐ€ ๋”ฑ ํ„ฐ์กŒ๋‹ค. 
์˜ˆ๋ฅผ ๋“ค์–ด ๋ช‡ ๋งŒ ๋ช…์ด ํ•œ์ •๋œ ์žฌ๊ณ ์˜ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•˜๋ ค๊ณ  ํ•  ๋•Œ?
์ˆ˜๋งŽ์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋Š” ๋ฐ์ดํ„ฐ์˜ ์žฌ๊ณ ๋Ÿ‰์„ ์กฐํšŒํ•˜๋ฉฐ ์žฌ๊ณ ๊ฐ€ ๋–จ์–ด์กŒ์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋ฉด ๋œ๋‹ค.
ํ•˜์ง€๋งŒ ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ฉด? ์ด๊ฑฐ ๋‚œ๊ฐํ•˜๋‹ค. ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๊ณ ์ฐฐ์„ ์ž‘์„ฑํ•˜๊ฒ ๋‹ค.

 

DB ๋™์‹œ์„ฑ ๋ฌธ์ œ

๋™์‹œ์— DB๋ฅผ ์กฐํšŒํ•  ๋•Œ๊ฐ€ ๋ฌธ์ œ์ด๋‹ค.

 

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” DBMS๋Š” Mysql

Mysql์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํŠธ๋žœ์žญ์…˜์˜ ๊ฒฉ๋ฆฌ ์ˆ˜์ค€์œผ๋กœ Level 2 Repeatable Read๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ์–ธ๋‘ ์˜์—ญ์„ ํ†ตํ•œ ๋‹ค์–‘ํ•œ ๋ฒ„์ „ ๋ณ„ MVCC๋ฅผ ํ†ตํ•ด ๋ฒ„์ „์— ๋งž๋Š” ๊ฐ’์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

ํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ธฐ์ˆ ์€ ๋ฌธ์ œ๊ฐ€ ์žˆ๊ธฐ ๋งˆ๋ จ์ด๋‹ค.

๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ Phantom Read์ด๋‹ค.

=> ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๊ฐ™์€ ์ฟผ๋ฆฌ๋ฅผ ๋‘ ๋ฒˆ ์ˆ˜ํ–‰ํ•  ๊ฒฝ์šฐ, ์ฒซ ๋ฒˆ์งธ ์ฟผ๋ฆฌ์—์„œ ์—†๋˜ ์œ ๋ น ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋‘ ๋ฒˆ์งธ ์ฟผ๋ฆฌ์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ํ˜„์ƒ

 

์ฐธ์กฐ : https://itpenote.tistory.com/616

 

Phantom Read

I. Phantom Read ์ •์˜ ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๊ฐ™์€ ์ฟผ๋ฆฌ๋ฅผ ๋‘ ๋ฒˆ ์ˆ˜ํ–‰ ์‹œ, ์ฒซ ๋ฒˆ์งธ ์ฟผ๋ฆฌ์—์„œ ์—†๋˜ ๋ ˆ์ฝ”๋“œ(์œ ๋ น, Phantom)๊ฐ€ ๋‘ ๋ฒˆ์งธ ์ฟผ๋ฆฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ํ˜„์ƒ ์ ˆ์ฐจ ์ ˆ์ฐจ ํŠธ๋žœ์žญ์…˜ ๋ฐ์ดํ„ฐ ์˜ˆ์ œ ์„ค๋ช… โ‘  Read Tra

itpenote.tistory.com

 

๋‚ด ํ”„๋กœ์ ํŠธ์—์„œ์˜ DB ๋™์‹œ์„ฑ ๋ฌธ์ œ

 

์กฐ๊ฑด 

=> ์ˆ˜ ๋งŒ๋ช…์˜ ์‚ฌ๋žŒ์ด ํ•œ์ •๋œ ์žฌ๊ณ ์˜ ์ƒํ’ˆ์„ ๊ตฌ๋งคํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ์ด๋•Œ ๋™์‹œ์— ์ฃผ๋ฌธ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ? (ํŒฌํ…€ ๋ฆฌ๋“œ ๋ฐœ์ƒ)

 

์ ˆ์ฐจ

์žฌ๊ณ ๋Š” ๋ฏฟ์„ ์ˆ˜ ์—†๋Š” ๊ฐ’์ด ๋œ๋‹ค.

 

ํ•ด๊ฒฐ๋ฒ•

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์˜ ๋ฝ์„ ์ด์šฉํ•˜์ž

=> ์žฌ๊ณ ๋ฅผ ํ™•์ธํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฆฌ์†Œ์Šค๋ฅผ ์ ์œ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. Mysql์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ ˆ์ฝ”๋“œ ๋ฝ์ด๋ฏ€๋กœ, ํ•ด๋‹น ๋ ˆ์ฝ”๋“œ์˜ ํŠธ๋žœ์žญ์…˜ ๋™์•ˆ ๋ฝ์„ ์ ์œ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ๋ฝ ์ ์œ 

=> For Update๋ฅผ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜ ์ˆ˜ํ–‰๋™์•ˆ ๋ฝ์„ ํš๋“ํ•ด ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋„ ๋ฆฌ์†Œ์Šค๋ฅผ ์ ์œ ํ•œ๋‹ค.

 

@Transactional
public String getkakaoPayUrl(OrderDTO orderDTO, HttpServletRequest request) throws RunOutOfStockException {

    /* ์žฌ๊ณ  ํ™•์ธ */
    int productStock = productMapper.selectStockOfProduct(orderDTO.getItemName());
    if (orderDTO.getQuantity() > productStock) {
        throw new RunOutOfStockException("ํ•ด๋‹น ์ƒํ’ˆ์ด ํ’ˆ์ ˆ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
    }

์„œ๋น„์Šค ๋ ˆ์ด์–ด์—์„œ ํŠธ๋žœ์žญ์…˜์„ ๊ฑด๋‹ค. 

/* ์žฌ๊ณ  ์ฐจ๊ฐ */
updateStock(productStock - orderDTO.getQuantity(), orderDTO.getItemName(), "product_name");

๊ฐ™์€ ๋ฉ”์„œ๋“œ ๋‚ด์˜ ๋˜ ๋‹ค๋ฅธ update ์ฟผ๋ฆฌ => ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ „๋ถ€ ๋กค๋ฐฑ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค. ํŠธ๋žœ์žญ์…˜์˜ ์›์ž์„ฑ!

 

์žฅ๋ฐ”๊ตฌ๋‹ˆ๋ฅผ ๊ฒฐ์ œํ•ด๋ณด์ž

๊ธฐ์กด ์ƒํ’ˆ ์žฌ๊ณ ๋Ÿ‰์€ 120๊ฐœ ์”ฉ์ด๋‹ค.

 

์„ฑ๊ณตํ•  ๊ฒฝ์šฐ

=> ๋‘ ๋ฒˆ ๊ฒฐ์ œํ–ˆ์œผ๋ฏ€๋กœ ์ œ๋Œ€๋กœ ์ˆ˜๋Ÿ‰ ์ฐจ๊ฐ์ด ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋ฝ์„ ๊ฑด๋‹ค๋Š” ๊ฒƒ์€ ์„ฑ๋Šฅ์˜ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ๋ณ„ํžˆ ์‹ ๊ฒฝ ์จ์„œ ์ฃผ์˜ํ•˜๋ฉฐ ์‚ฌ์šฉํ•ด์•ผ ๋  ๊ฒƒ ๊ฐ™๋‹ค.

 

์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•œ ๋ฆฌํŒฉํ† ๋ง!! (์ถ”๊ฐ€)

๋‹ค์Œ ๊ธ€์„ ์ฝ์–ด๋ณด์„ธ์š” ใ…Žใ…Ž

 

๋™์‹œ์„ฑ ์กฐํšŒ ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐ ์„ฑ๋Šฅ์— ๊ด€ํ•œ ๊ณ ๋ฏผ [Lock, Queue, Redis]

์ฃผ๋ฌธ ๊ฑด์— ๋Œ€ํ•œ ์ƒํ’ˆ ์žฌ๊ณ  ํŒŒ์•… ๋™์‹œ์„ฑ ๊ด€๋ จ ์ด์Šˆ์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•œ ํ•˜๋ฃจ๋‹ค. ํ”„๋กœ์ ํŠธ ๋ฆฌํŒฉํ† ๋ง์„ ์‹œ์ž‘ํ•˜๋ฉฐ ์ง€๋‚œ ๋„๋ฉ”์ธ๋“ค์€ ๊ธฐ๋ณธ crud API๋งŒ์„ ๋‹ค๋ฃจ์—ˆ๋‹ค. 5์ผ๋™์•ˆ JPA ๊ฐ•์˜๋“ค์„ ์ˆ˜๊ฐ•ํ•˜๋ฉฐ ๋ณธ๊ฒฉ์ ์œผ๋กœ

sweeeetgoguma.tistory.com

 

๋ฐ˜์‘ํ˜•