【问题标题】:Trapping Error 266 in SQL Server 2005在 SQL Server 2005 中捕获错误 266
【发布时间】:2010-11-02 23:41:32
【问题描述】:

有没有办法通过以某种方式包装 exec 语句在 JDBC 或 SQL 内部捕获 error 266

我们正在寻求开发一种保护措施,以防止存储过程以一种常见的方式保持打开状态而退出。这有助于防止与连接池结合使用时可能导致严重问题的程序员错误。

【问题讨论】:

  • 为存储过程提供模板不是更容易(也更有意义)吗?然后可以快速检查代码的正确性......
  • 已经完成了,包括标准错误处理,但是由于SQL Server 2005没有try/catch/finally的概念,只是try/catch,所以可以注入中间简单返回的逻辑使交易保持打开状态的交易。我们需要更好的解决方案来检测和监控这些类型的错误。
  • @Scott Markwell:finally 就在“END CATCH”之后!
  • @gbn,可能存在代码转义,在捕获后不会立即运行代码。在真正的 try/catch/finally 模式中,它将在哪里运行。
  • @Scott Markwell:如果使用 TRY/CATCH,则不会:任何未能进入 CATCH 块的错误都意味着代码几乎从未运行或编译过

标签: sql-server sql-server-2005 jdbc transactions


【解决方案1】:

是的。使用SET XACT_ABORT ON.

它抑制错误 266 并在任何情况下强制回滚,包括客户端命令超时,这只是中止。

这与 PerformanceDBA 提出的观点不同,这些观点大多有效。

其他链接:

【讨论】:

  • 一些非常有趣的材料,并提供了一些探索的途径,但是将 XACT_ABORT 设置为 ON 并不能提供捕获 266 的方法,由于程序员错误,有些代码情况不会产生触发 XACT_ABORT 的东西回滚,但仍然触发 266。
  • 这就是为什么你应该有一个 proc 模板 :-) 你是对的,但 SET XACT_ABORT ON 会抑制 266,否则会发生这种情况。
【解决方案2】:
  1. 编号较低的错误,15000 及以下 IIRC,以及较高的严重级别,中断执行。这意味着整个线程都被中断了,不可能将其捕获在存储的过程代码中。

  2. 无论如何,错误超出了 SQL 代码或存储过程的控制范围。编号较低的错误是“硬”错误,即使您确实捕获了它,您也无能为力。它在服务器(不是您的)域内。例如。硬盘错误; 1205.服务器决定,线程不能继续,终止spid。

  3. 捕获不是您管理、设置或控制的错误的外部域是不可行的。所以我无法理解你期望你能做到的基础。捕获(例如)硬件错误和死锁的唯一方法是编写自己的服务器。

  4. 但最重要的是这个。 在交易打开时处理用户交互,您违反了交易控制的基本法则(这是在您的权力范围内)。规则(40 年不变)是:

    • 没有交易打开的情况下执行所有用户交互
    • 完成后,终止进一步的用户交互
    • 开始交易,
    • 执行所有 DML,并且
    • 提交
      .
  5. 不遵守这些规则会导致各种容易预防的问题(通过遵守规则):

    • 不受控制的锁定持续时间
    • 挂起的交易(等待吃过午饭的用户)
    • 响应很慢,服务器空闲,等待锁
      .
      如果你开车,当然,你可以在郊区街道和购物商场里摆弄,但是一旦你在高速公路上开到一辆,你就不能低于限速;你不能停下来等乘客。如果你这样做,你会把所有人都挂起来。试图阻止会导致警察追捕你的手机电话,或者试图阻止警察拖你走,这在某种程度上超出了你的能力,尽管它们可能很强大。
      .
  6. 在正常情况下,当服务器遇到硬错误并取消您的 spid(当然包括回滚)时,问题就关闭了。符合 ANSI SQL 89(早于 92)的行为。事务是原子的和持久的。现在,如果您不为该模型编写代码(提供隔离和一致性),它就不是“事务”,它只是一串不受控制的跨时间和空间分布的 SQL,很容易中断;脆弱易受伤害。

    显然这意味着 NO AUTOCOMMIT 和 NO CHAINED,因为它违反了 ANSI SQL 标准。非常可悲的是(a)MS 提供了如此糟糕的功能,并且(b)人们使用它,却不了解危险和违规行为。

  7. 与其关心你认为服务器应该做什么和不应该做什么(这是徒劳的,因为它不会改变),我建议你对你生成的代码负责,并教育自己在设计和编写任何代码之前,重新了解服务器的实际工作方式、实际工作方式。

  8. 用你的话说,哦,它肯定会执行try/catch/finally,它捕获的一半错误会导致它让你大吃一惊,所以你的 try/catch永远无法执行。 您的 SQL 代码尝试最终 的概念不存在。 SQL 是一种高级数据库操作语言,而不是一种可以控制硬件资源的低级语言。

    如果你在高速公路上开车,你不能困住 (a) 你前面 10 公里的桥撞毁或 (b) 警察在你前面 1 公里关闭高速公路 em>

    试图控制不可控的东西当然是……

【讨论】:

  • 您假设编写代码的人类是绝对可靠的。我不能做出这样的假设。人类编写代码、审查代码、打包以进行部署。已分析的所有用例表明,在这种情况下,适当的操作过程是回滚挂起事务,如果未启用连接池,无论如何都会这样做。我并不是要防范服务器本身,而是要防范人为错误。有多种方法可以减轻人为错误,这是其中之一。
  • 为了让自己更清楚一点,错误 266 不会回滚事务,这是所希望的。
  • 相反,人类,尤其是 SQL 程序员,是容易犯错的;这就是为什么服务器必须捕获超出 pgmrs 控制等的错误并处理它的原因。这就是我这篇文章的要点。我仍然说,你有一个 pgmg 问题,因为你打开了一个 xact,当连接关闭时,实现我详述的是防止 pgmr 错误的正式方法。混合未/链式根本行不通。 MS 没有做很多它应该做的事情。
  • 另一个问题是,与数据库通信的应用程序引擎使用了连接池,因此,打开的事务会导致不同代码路径上的严重破坏,还会导致大量数据库锁定和事务回滚。
  • @Scott:这是我发布的类别之一。核心修复可能是在每个事务代码段的末尾添加:IF @@TRANCOUNT != 0 ROLLBACK TRAN。更好的方法是改进所有事务中的错误检查和代码块。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-08
  • 1970-01-01
相关资源
最近更新 更多