编写存储过程模式和错误报告

时间:2012-04-09 06:23:35

标签: sql stored-procedures exception-handling plpgsql

在创建复杂过程时,整个函数被视为事务或者我只是将整个函数放在begin ... end中。所以如果任何中间查询失败,系统就没有问题。那么我需要任何错误报告吗?或IF ... ELSE检查错误报告? (假设外键/唯一/等...约束已正确完成)

如果duplicate key value violates unique constraint或我应该依赖数据库引擎,我是否应该自己提出错误?

在编写存储过程的同时开发业务逻辑时,是否有任何模式要遵循?

我使用的是PostgreSqlPL/PgSQL,之前我常常ORM

1 个答案:

答案 0 :(得分:2)

据我了解,您正在编写要从客户端代码执行的函数。函数执行的全部内容将始终在一个事务中,无论您是否明确BEGIN事务,尽管您可以通过使用BEGIN / END块编码来在plpgsql中使用子事务。 EXCEPTION条款。这种子交易不是免费的,所以你只想在真正需要的时候使用它们。

如果可以声明性地声明实施业务规则所必需的不变量,那么几乎总是比在触发器中使用命令性代码强制执行它们更好。 CHECK约束,PRIMARY KEY约束,FOREIGN KEY约束,UNIQUE约束和(PostgreSQL独有的特性)EXCLUSION约束应该全部用于代替触发器代码当他们报道用例时。

如果您使用的是PostgreSQL 9.1或更高版本,那么在开始之前做出的最大决定是您将采用什么策略来处理并发事务之间的竞争条件。两个主要选择是,是否尝试跟踪所有可能的冲突并处理应用程序代码中的问题,或者仅使用可序列化的事务(您可以在postgresql.conf文件中使用该默认值)并让PostgreSQL对其进行排序。我在前者看到的最好的写作是:http://www.postgresql.org/files/developer/concurrency.pdf而关于后者的链接是:

http://www.postgresql.org/docs/current/interactive/mvcc.html

http://wiki.postgresql.org/wiki/SSI

如果使用SERIALIZABLE甚至REPEATABLE READ事务,则应以某种方式运行查询,以提供序列化失败的通用处理;也就是说,如果事务在SQLSTATE设置为“40001”或“40P01”时抛出异常,则应回滚失败的事务并从头开始重试。您不希望在运行查询的每个位置的应用程序代码中嵌入逻辑。如今,许多开发框架都允许使用事务性注释,这使得这很容易实现。我们只在我们的商店使用可序列化的交易,它确实简化了事情,知道如果你能证明交易本身就是正确的事情,那么它将在任何交易组合中做正确的事情,而无需任何特殊的编码来确保(除了如上所述处理序列化失败之外)。

请注意,由于使用了Serializable Snapshot Isolation,使用可序列化事务的PostgreSQL的性能非常接近于许多工作负载的不太严格的隔离级别;如果你因为害怕阻塞和僵局而一直在回避这个想法 - 不要。 PostgreSQL 9.1中的可序列化事务没有像使用严格的两阶段锁定(S2PL)的数据库那样的问题。

完全披露:与Dan R.K共同努力。麻省理工学院的港口,基于Michael J. Cahill和Sidney大学的论文,我帮助实现了PostgreSQL版本9.1的Serializable Snapshot Isolation,因为我们需要在我的工作场所使用该功能。我没有从使用它的任何人那里获得任何经济利益,但我个人认为这通常是要走的路。我希望,更多的是原因我在该功能上工作,而不是使用该功能的结果