我正在创建一些简单的帮助器类和方法来处理libpq,我想知道我是否从数据库收到错误 - (例如SQL错误),我应该如何处理它?</ p>
目前,每个方法都会返回一个bool,具体取决于操作是否成功,因此在继续执行新操作之前由用户进行检查。
然而,在阅读了libpq文档之后,如果发生错误,我能想到的最好的是我应该记录错误消息/状态,否则忽略。例如,如果应用程序处于事务中间,那么我相信它仍然可以继续(据我所知,Postgresql不会取消该事务)。
我可以用PostgreSQL / libpq做些什么来使这些错误的后果对数据库服务器安全,或者是无知更好的策略?
答案 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
。如果返回简化错误,请记录所有详细信息。
希望这很有用。