假设银行系统有一个表,某一列为账户存款余额,数据量假设为五千万条。
现在要求统计表内所有账户余额总和;
假设查询需要20分钟,13:00开始查询,13:20才能查询结束,
但是13:10的时候有一个事务,要将第1000万条数据余额扣减5000,将第4000万条数据增加4800,
问:查询结果是否准确?
请详细分析。
有Oracle、DB2、SqlServer都懂的朋友还可以分析一下各种数据库在这个处理上有何不同。
不要怕分数不够,还可以补加。
谢谢各位!
现在要求统计表内所有账户余额总和;
假设查询需要20分钟,13:00开始查询,13:20才能查询结束,
但是13:10的时候有一个事务,要将第1000万条数据余额扣减5000,将第4000万条数据增加4800,
问:查询结果是否准确?
请详细分析。
有Oracle、DB2、SqlServer都懂的朋友还可以分析一下各种数据库在这个处理上有何不同。
不要怕分数不够,还可以补加。
谢谢各位!
oracle 使用的“多版本模型”(undo 段)来确保读一致性,其关键在于合理设置事务提交后 undo 段的保留时间(undo_retention)。
对于 lz 提出的场景,
如果更新事务执行的时间较长,超过了 13:20(似乎不太可能哦),那么其更改数据对应 undo 段将一致保留(因为事务没有提交),对查询就没有什么影响。
如果更新事务执行的时间很短(如只有几秒),那么查询语句是否可以读取到一致的数据,就取决于 undo 段保留时间,如果设置的太短,那么 undo 段就有可能被其他事务覆盖,查询语句将可能无法读取到一致的数据。sql server 默认使用的“锁机制”来确保读一致性。对于 lz 提出的场景,查询语句会在查询期间对所查询的记录保持 s 锁,其会阻止更新事务对这些记录的修改,也就是说,更新事务要一致等到查询执行完毕才会被执行。
但是,在 sql server 2005 及以上版本,sql server 可以使用“行版本控制”(快照事务)来确保读一致性——通过在 tempdb 数据库中存储修改数据原先的版本。但是当 TEMPDB 数据库已满时,更新操作将停止生成行版本,但会继续;但是由于特定的行版本不存在,查询操作可能会失败。因此,其确保查询可以取到一致的数据的关键在于为 tempdb 数据库分配足够的空间。db2 太高级,就不了解了。
oracle、db2、sqlserver都支持一致性读取
对于oracle来说,13:10查询数据时,数据立即被“冻结“在这一时刻
(实际上,这是通过undo段来实现的)。
13:20查询统计出的数据也是13:10那一刻的帐户余额之和。
oracle是多版本的数据库,写数据也不会阻塞读数据,因此保证了读数据的准确性。
无论你并发不并发,你的查询,求和运算都是没有问题的,但是他的查询结果是对应一个具体的版本的。
本新鸟不懂……