我应该如何处理libgq中的postgresql错误

时间:2014-08-16 21:43:17

标签: c++ postgresql error-handling libpq

我正在创建一些简单的帮助器类和方法来处理libpq,我想知道我是否从数据库收到错误 - (例如SQL错误),我应该如何处理它?<​​/ p>

目前,每个方法都会返回一个bool,具体取决于操作是否成功,因此在继续执行新操作之前由用户进行检查。

然而,在阅读了libpq文档之后,如果发生错误,我能想到的最好的是我应该记录错误消息/状态,否则忽略。例如,如果应用程序处于事务中间,那么我相信它仍然可以继续(据我所知,Postgresql不会取消该事务)。

我可以用PostgreSQL / libpq做些什么来使这些错误的后果对数据库服务器安全,或者是无知更好的策略?

1 个答案:

答案 0 :(得分:6)

您应该检查错误中的SQLSTATE并根据进行处理决策。切勿尝试根据错误消息文本在代码中做出决定。

应用程序应该只针对某些类型的错误重试事务:

  • 序列化失败
  • 死锁检测事务中止

对于连接错误,您应该重新连接然后重新尝试该事务。

当然,您希望设置重试次数的限制,因此如果问题没有解决,则不会永远循环。

其他类型的错误无法通过再次尝试解决,因此应用程序应向客户端报告错误。语法错误?独特违规?检查约束违规?再次运行该语句无济于事。

a list of error codes in the documentation但文档并没有解释每个错误,但序言部分非常有用。

旁注:避免陷入的一个陷阱是在使用它们之前使用普通查询“测试”连接,并假设这意味着真正的查询不会失败。那是一场竞争。不要打扰测试连接;只需运行真实的查询并处理任何错误。

具体操作的细节取决于错误和应用程序。如果有一个总是正确的答案,libpq已经为你做了。

我的建议:

  • 在您必须重新运行之前,始终保留事务记录,直到您从数据库中获得确认提交为止。不要只是发射并忘记SQL语句。

  • 在没有断开连接的情况下重试事务并重新连接SQLSTATE 40001(serialization_failure)和40P01(deadlock_detected),因为这些是通常通过重新尝试解决的瞬态条件。您应该记录它们,因为它们有机会改善应用程序与数据库的交互方式,如果它们发生了很多,那么它们就是性能问题。

  • 至少对错误类08(连接例外)断开连接,重新连接并重试该事务一次。

  • 处理53300(too_many_connections)和53400(超出连接限制),并向用户提供具体且信息性错误。与其他53类条目相同。

  • 处理具有特定且信息性错误的类57的条目给用户。如果你得到query_cancelled(57014),请不要重试,这会让系统管理员非常生气。

  • 通过报告不同的错误来处理25006(read_only_sql_transaction),告诉用户您尝试写入只读数据库或使用只读事务。

  • 报告23505(UNIQUE违规)的其他错误,表明唯一约束或主键约束存在冲突。没有必要重试。

  • 错误类01不应该产生异常。

  • 将其他案例视为错误并将其报告给调用者,并提供问题的详细信息 - 最重要的是SQLSTATE。如果返回简化错误,请记录所有详细信息。

希望这很有用。