2011-02-23 70 views
0

当在事务中使用多个插入与select语句时,数据库如何跟踪事务期间的更改?如果事务处于打开状态的时间过长,是否会出现资源问题(如内存或硬盘空间)?是插入选择语句庞大?

+0

确切地理解你所要求的内容有点困难,但是当你提交一个事务时,你会提交作为该事务的一部分执行的所有更改。你到底在问什么? – 2011-02-23 16:31:05

+1

试图推断提问者的意图。这个问题的原始形式是无法回答的。 – 2011-02-23 16:34:51

+0

@罗伯特哈维:我希望我可以投票了你的编辑。 – derobert 2011-02-23 23:02:53

回答

0

对于大型交易您可能会遇到很多问题。首先,在大多数数据库中,您不希望逐行运行,因为一百万条记录需要几个小时。但是,在一个复杂语句中插入一百万条记录会导致涉及的表上的锁定并损害其他人的性能。如果你杀了交易,回滚也可能需要很长时间。通常最好的选择是批量循环。我通常一次测试50,000个,并根据需要多长时间提高或降低该组。我有一些数据库,在一次基于集合的操作中,我不会再使用1000个数据库。如果可能的话,应该为数据库运行的非高峰时段安排大型插入或更新。如果真的很大(一次性 - 通常是大数据迁移),您甚至可能想要关闭数据库进行维护,将其置于单用户模式并删除索引,执行插入和重新索引。

1

简短的回答是,它取决于选择的大小。在技​​术上,select是事务的一部分,但大多数选择不必“回滚”,所以DB更改的实际日志不包含select本身。它包含的内容是select语句的每个结果的新行作为插入语句。如果这个select语句是10k行,那么提交会相当大,但不会比在一个显式事务中写入10k个单独的insert语句更多。

1

这是如何工作的取决于数据库。例如,在Oracle中,它将需要UNDO空间(并且最终,如果用完了,您的事务将被中止,或者您的DBA会对您大喊)。在PostgreSQL中,它会阻止旧行版本的清空。在MySQL/InnoDB中,它将使用回滚空间,并可能导致锁定超时。

有几件事情的数据库必须使用空间:

  1. 存储哪些行的交易已经改变(旧值,新的值,或两者),以便能够进行回滚
  2. 饲养跟踪哪些数据对您的事务可见,以便维护一致的视图(在事务隔离级别,而非读取未提交)。这种开销通常会在您请求的隔离度越高时越大。
  3. 跟踪哪个数据是可见的其他交易
  4. 跟踪哪个对象,其交易已经改变,所以隔离规则得到遵守,特别是在可序列化隔离(除非整个数据库中读取未提交运行)。 (可能没有太多的空间,但大量的锁)。

一般而言,您希望您的事务尽快提交。所以,例如,你不想让一个空闲的连接打开。如何最好地进行批量插入取决于数据库(通常,一次事务中的许多插入比每次插入一次事务更好)。当然,交易的主要目的是数据完整性。