๐ŸŒฟ Spring

[SpringBoot] UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only ํ•ด๊ฒฐํ›„๊ธฐ

์—ฐ_์šฐ๋ฆฌ 2022. 12. 6. 00:17
๋ฐ˜์‘ํ˜•

๋ชฉ์ฐจ

     

     

     

    ์ƒํ™ฉ

    1. ์ด๋ฒคํŠธ์— ๋‹น์ฒจ๋œ ๊ฒฝ์šฐ ํœด๋Œ€ํฐ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  [์ฟ ํฐ๋ฐ›๊ธฐ] ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ฟ ํฐ์ด ์ฆ‰์‹œ ๋ฐœ์†ก๋œ๋‹ค.

     

    2. ๊ทผ๋ฐ ๊ฐ€๋”์”ฉ [์ฟ ํฐ๋ฐ›๊ธฐ] ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฐ์ฑ„๋กœ ์•„๋ฌด๋Ÿฐ ๋ฐ˜์‘์ด ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

        (๋ธŒ๋ผ์šฐ์ € ์ž์ฒด๊ฐ€ ๋ฉˆ์ถ˜๋‹ค๋˜๊ฐ€... ์•„๋ฌด๋Ÿฐ ์•ก์…˜ ์—†์ด ๊ทธ๋ƒฅ ๋Œ€๊ธฐ๋งŒ ํ•œ๋‹ค๋˜๊ฐ€...)

     

    3. ๊ธฐ๋‹ค๋ ค๋„ ์‘๋‹ต์ด ์—†์œผ๋‹ˆ ์‚ฌ๋žŒ๋“ค์€ [์ฟ ํฐ ์•ˆ๋ฐ›๊ธฐ] ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ๋‹ค.

     

    4. [์ฟ ํฐ ์•ˆ๋ฐ›๊ธฐ] ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋‹น์ฒจ๋‚ด์—ญ์„ ์ดˆ๊ธฐํ™”์‹œํ‚จ๋‹ค. (๋‹ค๋ฅธ์‚ฌ๋žŒ์—๊ฒŒ ํ• ๋‹น๋˜์–ด์•ผํ•˜๋ฏ€๋กœ)

     

     

    ์„œ๋ฒ„์— ์ฐํžŒ ๋กœ๊ทธ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

    2022-12-05 10:45:24 ์ฟ ํฐ๋ฐ›๊ธฐ          ์‹œ์ž‘
    
    2022-12-05 10:45:25 ์ฟ ํฐ์•ˆ๋ฐ›๊ธฐ        ์‹œ์ž‘
    
    2022-12-05 10:45:25 ์ฟ ํฐ๋ฐ›๊ธฐ-์ฟ ํฐ๋ฐœ์†ก ์„ฑ๊ณต
    
    2022-12-05 10:45:26 ์ฟ ํฐ์•ˆ๋ฐ›๊ธฐ        ์ข…๋ฃŒ 
    
    2022-12-05 10:45:27 ์ฟ ํฐ๋ฐ›๊ธฐ          ์ข…๋ฃŒ << Error!!!
    
    UnexpectedRollbackException: Transaction silently rolled back 
    because it has been marked as rollback-only....

     

     

    ์ผ๋‹จ ์ฟ ํฐ์ด ๋ฐœ์†ก๋˜์—ˆ๊ณ 

    DB์— ํœด๋Œ€ํฐ๋ฒˆํ˜ธ์™€ ๋‹น์ฒจ๋‚ด์—ญ์„ ๋ณด๋‹ˆ ๋กค๋ฐฑ๋˜์–ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚ ์•„๊ฐ„ ์ƒํ™ฉ์ด์˜€๋‹ค

    ใ…Žใ„ทใ„ท...... ์•„์˜ˆ ์ด๋ฒคํŠธ ๋ฏธ์ฐธ์—ฌํ•œ ๊ณ ๊ฐ์œผ๋กœ ๋‚˜์˜ด....

     

     

    ๋” ๊ณ ๋ คํ•ด์•ผํ•  ์ ์€ ์œ„์—์ฒ˜๋Ÿผ [์ฟ ํฐ์•ˆ๋ฐ›๊ธฐ] ์ข…๋ฃŒ ์ดํ›„ [์ฟ ํฐ๋ฐ›๊ธฐ] ์ข…๋ฃŒ๋กœ ์ˆœ์„œ๊ฐ€ ๊ณ ์ •๋˜์–ด์žˆ์ง€ ์•Š๊ณ 

    ์–ด๋–ค๊ฒŒ ๋จผ์ € ์ˆ˜ํ–‰๋ ์ง€ ๋ชจ๋ฅธ๋‹ค๋Š” ์ ...

     

     

     

     

    ์‹œ๋„ํ•œ ๊ฒƒ 

    Jpa & Querydsl Lock ์„ค์ • 

    //jpa
    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
    
    //querydsl
    query.setLockMode(LockModeType.PESSIMISTIC_WRITE);

    [์ฟ ํฐ๋ฐ›๊ธฐ]์™€ [์ฟ ํฐ์•ˆ๋ฐ›๊ธฐ] ์—์„œ id(15๋ฒˆ)๋กœ ์กฐํšŒํ•  ๋•Œ

    ๋น„๊ด€์  ๋ฝ์„ ์ ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์ฝ๊ธฐ๋„ ์“ฐ์ง€๋„ ๋ชปํ•˜๊ฒŒ ํ•˜์˜€๋‹ค.

     

    select๋ฌธ ๋’ค์— for update๊ฐ€ ๋ถ™๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์˜€๋Š”๋ฐ... ์กฐํšŒ๊ฐ€ ๋œ๋‹ค..!

    PESSIMISTIC_WRITE๋Š” ๋ถ„๋ช… ์ฝ๊ธฐ๋„ ์“ฐ์ง€๋„ ๋ชปํ•œ๋‹ค๊ทธ๋žฌ๋Š”๋ฐ... ์กฐํšŒ๊ฐ€๋œ๋‹ค......

     

    ๋‚ด๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ์ž˜๋ชปํ•œ๊ฒƒ์ผ์ˆ˜๋„ ์žˆ์ง€๋งŒ.. ๋‹ค๋ฅธ๋ถ„๋“ค๋„ ๋ช‡๋ฒˆ ํ…Œ์ŠคํŠธ ํ•ด๋ดค์ง€๋งŒ ์กฐํšŒ๊ฐ€ ๋˜์—ˆ๊ณ ,

    update๋ฌธ์ด ๋‚˜๊ฐˆ๋•Œ ๋˜‘๊ฐ™์ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ ๋กค๋ฐฑ๋˜์–ด์„œ ์ด ๋ฐฉ๋ฒ•์€ ์‹คํŒจ

     

     

     

     

     

    ๋‚˜์˜ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

    update ~~ where ~~ ์กฐ๊ฑด ์„ค์ •

    ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒดํฌํ•ด์„œ ์ œ์–ดํ•˜๊ธฐ์—” ์ข€ ์–ด๋ ต๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด์„œ Query๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค!

    ์–ด์ฐจํ”ผ DB์—์„œ update๋ฌธ์€ 1๋ฒˆ์— 1๊ฐœ๋งŒ ์ˆ˜ํ–‰๋  ๊ฒƒ์ด๋‹ค.

     

     

    [์ฟ ํฐ ๋ฐ›๊ธฐ], [์ฟ ํฐ ์•ˆ๋ฐ›๊ธฐ] ์—์„œ ์กฐํšŒํ•  ๋• ์•„๋ž˜ ๊ฐ์ฒด๋ฅผ ๋˜‘๊ฐ™์ด ์กฐํšŒํ•˜๊ฒŒ๋œ๋‹ค

    ๋‹น์ฒจ๊นŒ์ง€ ๋จ. ํœด๋Œ€ํฐ๋ฒˆํ˜ธ ์ž…๋ ฅํ•˜๋ฉด ๋จ.

     

     

    CASE 1 ) 

    [์ฟ ํฐ ์•ˆ๋ฐ›๊ธฐ] ๋จผ์ € ์ˆ˜ํ–‰

    update ~ 
    set participate = 'N', win = 'N' 
    where phone is null

    ์ฐธ์—ฌ, ๋‹น์ฒจ๋‚ด์—ญ ์ดˆ๊ธฐํ™” ํ›„

     

    [์ฟ ํฐ ๋ฐ›๊ธฐ] ๋จผ์ € ์ˆ˜ํ–‰

    update ~ 
    set participate = 'Y', win = 'Y', phone = '010-0000-0000' 
    where phone is null

    participate์™€ win์€ select ์‹œ ๊ฐ€์ ธ์™”๋˜ ๊ฐ’์œผ๋กœ ๋˜‘๊ฐ™์ด ๋ฎ์–ด์ฃผ์–ด์„œ ๋‹น์ฒจ ์ด๋ ฅ์ด ๋‚จ๋„๋ก ํ•œ๋‹ค.

    ์ฟ ํฐ๋ฐ›๊ธฐ ์ ์šฉ ํ›„

     


     

     

    CASE 2 )

    [์ฟ ํฐ ๋ฐ›๊ธฐ] ๋จผ์ € ์ˆ˜ํ–‰

    update ~ 
    set participate = 'Y', win = 'Y', phone = '010-0000-0000' 
    where phone is null

    ์ฟ ํฐ๋ฐ›๊ธฐ ์ ์šฉ ํ›„

     

    [์ฟ ํฐ ์•ˆ๋ฐ›๊ธฐ] ๋‚˜์ค‘ ์ˆ˜ํ–‰

    update ~ 
    set participate = 'N', win = 'N' 
    where phone is null

    phone is null ์ด ์•„๋‹ˆ๋‹ˆ ํ•ด๋‹น update๋ฌธ์€ ์•„์˜ˆ ๋ฌด์‹œ๋จ!! 

     

    ์ฟ ํฐ์•ˆ๋ฐ›๊ธฐ๋Š” ๋ฌด์‹œ๋จ

     


     

     

     

     

     

    Transactional Propagation ์…‹ํŒ…

    update๋ฌธ์ด ๋‚˜๊ฐ€๋„ ๋‹ค๋ฅธ๋กœ์ง์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ๋กค๋ฐฑ๋˜๋ฉด ์•ˆ๋˜๋‹ˆ๊นŒ..

    rollbackFor์„ ์“ฐ๊ธฐ์—” ์ข€.. ๋ถ€๋‹ด๋˜์–ด์„œ propgation์„ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Response SendCoupone(~~){
        
        //์ฐธ์—ฌ์ •๋ณด ์ €์žฅ
        saveParticipate();
    
        //๋‹น์ฒจ์ •๋ณด ์ €์žฅ
        saveWinner();
        
        //์ฟ ํฐ ๋ฐœ์†ก
        sendCoupon();
    
        return response;
    }

    ํ•ด๋‹น ์„ค์ •์„ ํ•ด์ฃผ๋ฉด ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•œ๋‹ค. 

    ์ฐธ์—ฌ์ •๋ณด ์ €์žฅ ๋”ฐ๋กœ, ๋‹น์ฒจ์ •๋ณด ์ €์žฅ ๋”ฐ๋กœ, ์ฟ ํฐ๋ฐœ์†ก ๋”ฐ๋กœ๋”ฐ๋กœ ๊ฐ๊ฐœ์ „ํˆฌํ•˜๋ฉฐ ์ปค๋ฐ‹๋œ๋‹ค

     

     

     

     


     

    ์•ž์„œ ๋งํ•œ [์ฟ ํฐ๋ฐ›๊ธฐ], [์ฟ ํฐ์•ˆ๋ฐ›๊ธฐ]๊ฐ€ ๋™์‹œ์— ๋“ค์–ด์˜ค๋Š” ๋นˆ๋„์ˆ˜๊ฐ€ ์ƒ๊ฐ๋ณด๋‹ค ์ข€ ์žˆ์–ด์„œ 

    ๊ณ„์† ์ € ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒ๋˜๋Š” ์ƒํ™ฉ์ด์˜€๋‹ค (์ฐจ๋ผ๋ฆฌ ์ฃฝ์—ฌ...)

     

     

    ์ผ๋‹จ์€ update๋ฌธ๊ณผ propagation 2๊ฐ€์ง€ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ

    ๋กค๋ฐฑ๋˜์–ด์„œ ๋‚ ์•„๊ฐ€๋Š” ๋ฐ์ดํ„ฐ๋„ ์žก์•„๋ƒˆ๊ณ , ์—๋Ÿฌ ๋ฐœ์ƒํ•˜๋Š” ๋นˆ๋„์ˆ˜๋„ ์—„์ฒญ ๋‚ฎ์ถ”์—ˆ๋‹ค!

     

    ๋‚ด ๋ฐฉ๋ฒ•์ด ์ •๋‹ต์€ ์•„๋‹ˆ์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋‹ค๋Š” ๊ธฐ๋ก์šฉ ํ›„๊ธฐ~~~ ๋!

     

     

     

     

     

     

     

     

     

    ++ ๋Œ“๊ธ€ ์ถ”๊ฐ€ 

    ๋”๋ณด๊ธฐ

    ์ข‹์€ ์˜๊ฒฌ์„ ๋‚จ๊ฒจ์ฃผ์…”์„œ ๋‚˜์ค‘์— ๋‹ค์‹œ ์‚ดํŽด๋ณด๋ คํ•œ๋‹ค!

     

     

     

     

     

     

     

     

    ๋ฐ˜์‘ํ˜•
    • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
    • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
    • ํŠธ์œ„ํ„ฐ ๊ณต์œ ํ•˜๊ธฐ
    • ๊ตฌ๊ธ€ ํ”Œ๋Ÿฌ์Šค ๊ณต์œ ํ•˜๊ธฐ
    • ์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ