【问题标题】:Does rollBack improve performance?回滚会提高性能吗?
【发布时间】:2012-05-05 09:42:51
【问题描述】:

我刚刚成功尝试使用 beginTransaction() 在我的项目中使用 PHP 执行我的 sql 语句。我有一系列项目需要写入数据库,并且每个项目都必须在存储之前针对某些内容进行验证。关闭数据库的自动提交行为的好处之一是,如果中间出现问题,您可以回滚整个事务。在我的项目中,如果一项无效,整个数组不应该记录在数据库中,这就是我选择使用这种方法的原因。

现在我只是想知道这在性能方面是否真的是更好的方法?因为即使验证了数组中的最后一项,我仍然需要手动 commit() 之前的执行。 commit是否重复sql执行?

我现在能想到的唯一优势是,如果您想验证所有项目(假设所有项目都有效),则只需执行一个循环而不是两个循环,然后编写每个循环。

【问题讨论】:

  • SQL不是数据库产品。它只是许多 RDBMS 使用的一种语言。您使用的是什么数据库系统,什么版本?
  • 稍微 OT:如果可以通过查看数据库状态和更改本身来确定更改的有效性,那么可以说最好将验证放在 BEFORE 触发器中,以便业务无论使用哪个应用程序代码客户端,都会应用逻辑。

标签: php sql postgresql database-performance


【解决方案1】:

首先验证一切,然后开始事务,数据库交互。进行交易不是为了帮助验证数据。

【讨论】:

  • 就像我说的,如果我先验证一切,假设一切正常,我必须再次循环数组以将每个项目写入数据库。
  • 这通常是个坏主意。仅仅因为某件事在事务开始之前的某个时间为真,并不能证明当你去应用事务时它仍然为真,除非在事务之外有一些同步数据库本身。事务正是一种机制,您可以通过它在面对并发修改时确保数据库完整性。
【解决方案2】:

Commit 不会重复执行 SQL。

通常,在事务中工作时,每当您执行 INSERT/UPDATE/DELETE 语句时,数据库都会将记录/数据页的副本复制到事务日志中,然后执行实际的记录更改。

如果其他人在您的交易过程中试图访问这些记录/数据页面,他们将被重定向到交易日志中的副本。

那么,当你执行commit的时候,数据库本身的数据已经更新了,服务器只需要删除事务日志就可以了。

如果您回滚而不是提交,那么数据库服务器会通过事务日志回溯,将您更新的所有记录/数据页面恢复到其原始状态,并删除每个事务日志条目。

因此,回滚是一种开销,因为数据库服务器必须将数据恢复到其事务前状态。

【讨论】:

  • 此回滚实现的描述不适用于 PostgreSQL。使用 PG,更新前的记录不会复制到任何地方,它们会保留在原地。系统在任何时间点都知道一行是否是最新的以及它的事务 ID。开销主要是在将来的某个时候,VACUUM 必须运行以回收这些未使用的行版本使用的磁盘空间,但对于提交和回滚都是如此。
  • 所以 Daniel 所说的意味着 PostgreSQL 上的回滚速度非常快。
【解决方案3】:

您可以使用保存点。来自manual

BEGIN;
     INSERT INTO table1 VALUES (1);
     SAVEPOINT my_savepoint;
       INSERT INTO table1 VALUES (2);
     ROLLBACK TO SAVEPOINT my_savepoint;
     INSERT INTO table1 VALUES (3); 
COMMIT;

您仍然需要验证您的输入,但您现在可以在单个事务中回滚。使用事务可以使数据库更快,因为(隐式)提交更少。

【讨论】:

  • +1 - 除非您要走很远并且您的事务需要很长时间和/或在其过程中锁定许多表并开始阻塞不必要的并发操作。然后你应该把它分成更小的事务(以一种聪明的方式)。
  • 在问题中明确指出,如果任何一项验证失败,则不应应用任何一项;所以这个建议完全适得其反。
猜你喜欢
  • 2013-04-12
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 2010-10-23
  • 2012-12-14
相关资源
最近更新 更多