在创建复杂过程时,整个函数被视为一个事务,或者如果我只是将整个函数放在一个begin ... end中。因此,如果任何中间查询失败,系统中就不会出现问题。那么,我需要任何错误报告吗?还是IF ... ELSE检查错误报告?(假设外键/唯一/等)(适当地完成约束)
如果duplicate key value violates unique constraint或我应该依赖数据库引擎,我是否需要自己提出一个错误?
在编写存储过程时,在将业务逻辑开发为时,是否有任何模式可遵循?
我用的是PostgreSql和PL/PgSQL,我以前做过ORM
发布于 2012-04-09 12:33:59
据我所知,您正在编写从客户端代码执行的函数。函数执行的全部将始终在一个事务中,无论您是否显式地BEGIN一个事务,尽管您可以通过使用BEGIN/END块编码EXCEPTION子句在plpgsql中使用子事务。这样的子事务不是免费的,所以您只想在真正需要的时候使用它们。
在强制执行业务规则所必需的不变量可以声明的地方,这几乎总是比在触发器中使用命令式代码强制执行它们更好。当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”,则应回滚失败的事务并从头开始重试。您不希望在运行查询的每个地方的应用程序代码中嵌入该逻辑。如今,许多开发框架都允许使用事务性注释,从而使其易于实现。我们只在我们的商店中使用可序列化的事务,并且它确实简化了一些事情:如果您能够证明一个事务本身做正确的事情,那么它将在任何事务组合中做正确的事情,而不需要任何特殊的编码来确保(除了处理上面提到的序列化失败之外)。
请注意,由于使用可序列化快照隔离,使用可序列化事务的PostgreSQL的性能非常接近于许多工作负载的不那么严格的隔离级别;如果您由于担心阻塞和死锁而一直回避这种想法--请不要。PostgreSQL 9.1中的可序列化事务不会出现类似于使用严格的两阶段锁定(S2PL)的数据库这样的问题。
完全披露:在与麻省理工学院的丹·R·K·波特(DanR.K. Ports )的共同努力中,基于西德尼大学( Sidney University )的迈克尔·J·卡希尔( Michael J. Cahill et all )的论文,我帮助实现了PostgreSQL版本9.1的可序列化快照隔离,因为我们需要我的工作场所的功能。我没有从其他人使用它得到任何经济利益,但我个人认为这是一般的道路。我希望这更多的是我做这个特性的原因,而不是做这个特性的结果。
https://stackoverflow.com/questions/10069706
复制相似问题