回答

收藏

从存储过程catch块处理死锁重试是一个好主意吗

技术问答 技术问答 220 人阅读 | 0 人回复 | 2023-09-14

根据我的理解,不可能完全防止事务陷入僵局。
6 f9 [8 s; j+ e. E我想拥有从应用程序代码的角度来看永不失败的事务。因此,我已经看到了用于Microsoft SQL的这种模式,我想知道这是否是个好主意?
* d2 g: ]+ c7 w* J    DECLARE @retry  tinyint
3 l! U( ^7 A8 b, \, Q    SET @retry  = 5, j8 p  D  u: W1 k0 S1 ?
    WHILE @retry >0& r) N5 I6 A% `/ ], e) T
    BEGIN' ]. O  \, C+ t1 u3 d
      BEGIN TRANSACTION
& M# s' a" p3 m, |      BEGIN TRY: K. i, L! v3 F1 q1 }
        // do transaction her8 Q! g/ x  l2 P- ^; L6 t/ q
        COMMIT
% D' Y7 a2 Q" C& B        BREAK
6 a" m) A; v7 m% D9 g      END TRY
8 Y/ j" S2 l7 H. t      BEGIN CATCH: k* S' c$ R! \- y% j; d
        ROLLBACK7 {) V9 L5 S$ I4 @9 ^/ P( N
        if (ERROR_NUMBER() = 1205 OR ERROR_NUMBER() = 1222)
- P6 w. m6 k+ R! j+ I# r. K        BEGIN* Z! z! U; i9 Y1 |
          SET @retry = @retry - 1
6 U8 j0 H" c" i5 ?          IF @retry = 0
9 d) o2 s5 V/ [* L             RAISEERROR('Could not complete transaction',16,1);
8 ]0 n, e5 {8 O- A+ g- _          WAITFOR DELAY '00:00:00.05' -- Wait for 50 ms/ y2 s+ |. J; {- o- p, n- r
          CONTINUE
* X( r. m! H- m' k! B. Z4 c        END
& Q" B1 F) j( Q; b$ G        ELSE
* @* Y0 W/ {0 u* g% i        BEGIN1 o( ~# g) [* j% q2 k% n
          RAISEERROR('Non-deadlock condition encountered',16,1);  i# t8 {) j! P" x! W
          BREAK;
9 M- I! y  u+ ~        END4 S* ?1 h3 s' c0 g4 _- g1 ^
      END CATCH;
- Z# {$ n( {/ R- J    END" ~( e1 @6 P+ K. U6 T9 W' M4 F
               
+ y4 g% b. X4 W' b$ V- u: E解决方案:
) z5 d3 Y* ]2 \               
% j0 f7 n4 h, q7 |' ~) A% R& u8 @1 V/ X6 P" s8 r4 h6 M) C/ W. m
1 y, Q8 T& u9 A& o4 p- O; t9 n: l7 V
                客户端代码中应包含可恢复错误的重试逻辑。
2 j: ~4 u2 Z* F$ f$ r4 _4 p对于死锁,MSDN声明在那做
# g7 Z8 q$ y. D9 K8 r. E9 g% N如果重试SQL,则最终可能会遇到CommandTimeout。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则