现在要求统计表内所有账户余额总和;
假设查询需要20分钟,13:00开始查询,13:20才能查询结束,
但是13:10的时候有一个事务,要将第1000万条数据余额扣减5000,将第4000万条数据增加4800,
问:查询结果是否准确?
请详细分析。
有Oracle、DB2、SqlServer都懂的朋友还可以分析一下各种数据库在这个处理上有何不同。
不要怕分数不够,还可以补加。
谢谢各位!
22 个解决方案
#1
这东西得看你13:10的事务提交的时间是在少于10分钟
#2
oracle应该会根据归档的日志查询到13:20之前提交了数据库的所有的记录。
#3
愚见。。。呵呵。。
#4
oracle 和 sql server 数据库默认都可以保证语句级的读一致性,也就是保证在查询语句执行期间所查询的数据保持一致。
但是,oracle 和 sql server 所使用的技术有差别。
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 和 sql server 所使用的技术有差别。
oracle 使用的“多版本模型”(undo 段)来确保读一致性,其关键在于合理设置事务提交后 undo 段的保留时间(undo_retention)。
对于 lz 提出的场景,
如果更新事务执行的时间较长,超过了 13:20(似乎不太可能哦),那么其更改数据对应 undo 段将一致保留(因为事务没有提交),对查询就没有什么影响。
如果更新事务执行的时间很短(如只有几秒),那么查询语句是否可以读取到一致的数据,就取决于 undo 段保留时间,如果设置的太短,那么 undo 段就有可能被其他事务覆盖,查询语句将可能无法读取到一致的数据。
sql server 默认使用的“锁机制”来确保读一致性。对于 lz 提出的场景,查询语句会在查询期间对所查询的记录保持 s 锁,其会阻止更新事务对这些记录的修改,也就是说,更新事务要一致等到查询执行完毕才会被执行。
但是,在 sql server 2005 及以上版本,sql server 可以使用“行版本控制”(快照事务)来确保读一致性——通过在 tempdb 数据库中存储修改数据原先的版本。但是当 TEMPDB 数据库已满时,更新操作将停止生成行版本,但会继续;但是由于特定的行版本不存在,查询操作可能会失败。因此,其确保查询可以取到一致的数据的关键在于为 tempdb 数据库分配足够的空间。
db2 太高级,就不了解了。
#5
只能关注了.
#6
学习了。。。
#7
#8
#9
#10
不脏读是数据库管理系统的最起码要求。
oracle、db2、sqlserver都支持一致性读取
对于oracle来说,13:10查询数据时,数据立即被“冻结“在这一时刻
(实际上,这是通过undo段来实现的)。
13:20查询统计出的数据也是13:10那一刻的帐户余额之和。
oracle、db2、sqlserver都支持一致性读取
对于oracle来说,13:10查询数据时,数据立即被“冻结“在这一时刻
(实际上,这是通过undo段来实现的)。
13:20查询统计出的数据也是13:10那一刻的帐户余额之和。
#11
当然准确,不会有任何问题, 不过建议你要优化你的大事务,查询方面也在作一下优化,否则01555会伴随你的。
#12
#13
别的数据库原理我没研究,说说oracle.
oracle是多版本的数据库,写数据也不会阻塞读数据,因此保证了读数据的准确性。
无论你并发不并发,你的查询,求和运算都是没有问题的,但是他的查询结果是对应一个具体的版本的。
oracle是多版本的数据库,写数据也不会阻塞读数据,因此保证了读数据的准确性。
无论你并发不并发,你的查询,求和运算都是没有问题的,但是他的查询结果是对应一个具体的版本的。
#14
学习了。。。
#15
学习了
#16
#17
在orcle中查询的开始时间是13:00 到13:20 结束,在13:00时数据没有发生变化,所以select捞出来的数据是13:00这个时间点的数据,而不会用13:10这个时间点更新的数据
#18
#19
按10楼和17楼说的,13:00开始查询,那么不论什么时候结束,结果都是13:00这个时刻的数据,是吧。
那么数据库如何做到在13:00那一刻把数千万的数据都冻结起来呢?13:20的时候读取的数据是表中的数据还是13:00时刻数据的“快照”呢?
那么数据库如何做到在13:00那一刻把数千万的数据都冻结起来呢?13:20的时候读取的数据是表中的数据还是13:00时刻数据的“快照”呢?
#20
不需要冻结呀,oracle是根据scn来的。
#21
scn是啥?
本新鸟不懂……
本新鸟不懂……
#22
你的oracle的undo空间足够的话,当推进到中间变化的2行时,它会根据undo段自动的去查13:00那个时间的数值的
sqlserver的话,在这个事务开始的时候,会给表数据加上共享锁(行,键,或者升级为表锁),根据你汇总数据的group by条件,如果是某些键,sqlserver可能会用到键锁,尽量只锁定你需要的这部分数据.
转账事务可以读取,但不能修改第一个事务放置了共享锁的数据.你13:10开始的转账事务会堵在那,直到13:20你的汇总钱的事务完成
sqlserver的话,在这个事务开始的时候,会给表数据加上共享锁(行,键,或者升级为表锁),根据你汇总数据的group by条件,如果是某些键,sqlserver可能会用到键锁,尽量只锁定你需要的这部分数据.
转账事务可以读取,但不能修改第一个事务放置了共享锁的数据.你13:10开始的转账事务会堵在那,直到13:20你的汇总钱的事务完成
#1
这东西得看你13:10的事务提交的时间是在少于10分钟
#2
oracle应该会根据归档的日志查询到13:20之前提交了数据库的所有的记录。
#3
愚见。。。呵呵。。
#4
oracle 和 sql server 数据库默认都可以保证语句级的读一致性,也就是保证在查询语句执行期间所查询的数据保持一致。
但是,oracle 和 sql server 所使用的技术有差别。
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 和 sql server 所使用的技术有差别。
oracle 使用的“多版本模型”(undo 段)来确保读一致性,其关键在于合理设置事务提交后 undo 段的保留时间(undo_retention)。
对于 lz 提出的场景,
如果更新事务执行的时间较长,超过了 13:20(似乎不太可能哦),那么其更改数据对应 undo 段将一致保留(因为事务没有提交),对查询就没有什么影响。
如果更新事务执行的时间很短(如只有几秒),那么查询语句是否可以读取到一致的数据,就取决于 undo 段保留时间,如果设置的太短,那么 undo 段就有可能被其他事务覆盖,查询语句将可能无法读取到一致的数据。
sql server 默认使用的“锁机制”来确保读一致性。对于 lz 提出的场景,查询语句会在查询期间对所查询的记录保持 s 锁,其会阻止更新事务对这些记录的修改,也就是说,更新事务要一致等到查询执行完毕才会被执行。
但是,在 sql server 2005 及以上版本,sql server 可以使用“行版本控制”(快照事务)来确保读一致性——通过在 tempdb 数据库中存储修改数据原先的版本。但是当 TEMPDB 数据库已满时,更新操作将停止生成行版本,但会继续;但是由于特定的行版本不存在,查询操作可能会失败。因此,其确保查询可以取到一致的数据的关键在于为 tempdb 数据库分配足够的空间。
db2 太高级,就不了解了。
#5
只能关注了.
#6
学习了。。。
#7
#8
#9
#10
不脏读是数据库管理系统的最起码要求。
oracle、db2、sqlserver都支持一致性读取
对于oracle来说,13:10查询数据时,数据立即被“冻结“在这一时刻
(实际上,这是通过undo段来实现的)。
13:20查询统计出的数据也是13:10那一刻的帐户余额之和。
oracle、db2、sqlserver都支持一致性读取
对于oracle来说,13:10查询数据时,数据立即被“冻结“在这一时刻
(实际上,这是通过undo段来实现的)。
13:20查询统计出的数据也是13:10那一刻的帐户余额之和。
#11
当然准确,不会有任何问题, 不过建议你要优化你的大事务,查询方面也在作一下优化,否则01555会伴随你的。
#12
#13
别的数据库原理我没研究,说说oracle.
oracle是多版本的数据库,写数据也不会阻塞读数据,因此保证了读数据的准确性。
无论你并发不并发,你的查询,求和运算都是没有问题的,但是他的查询结果是对应一个具体的版本的。
oracle是多版本的数据库,写数据也不会阻塞读数据,因此保证了读数据的准确性。
无论你并发不并发,你的查询,求和运算都是没有问题的,但是他的查询结果是对应一个具体的版本的。
#14
学习了。。。
#15
学习了
#16
#17
在orcle中查询的开始时间是13:00 到13:20 结束,在13:00时数据没有发生变化,所以select捞出来的数据是13:00这个时间点的数据,而不会用13:10这个时间点更新的数据
#18
#19
按10楼和17楼说的,13:00开始查询,那么不论什么时候结束,结果都是13:00这个时刻的数据,是吧。
那么数据库如何做到在13:00那一刻把数千万的数据都冻结起来呢?13:20的时候读取的数据是表中的数据还是13:00时刻数据的“快照”呢?
那么数据库如何做到在13:00那一刻把数千万的数据都冻结起来呢?13:20的时候读取的数据是表中的数据还是13:00时刻数据的“快照”呢?
#20
不需要冻结呀,oracle是根据scn来的。
#21
scn是啥?
本新鸟不懂……
本新鸟不懂……
#22
你的oracle的undo空间足够的话,当推进到中间变化的2行时,它会根据undo段自动的去查13:00那个时间的数值的
sqlserver的话,在这个事务开始的时候,会给表数据加上共享锁(行,键,或者升级为表锁),根据你汇总数据的group by条件,如果是某些键,sqlserver可能会用到键锁,尽量只锁定你需要的这部分数据.
转账事务可以读取,但不能修改第一个事务放置了共享锁的数据.你13:10开始的转账事务会堵在那,直到13:20你的汇总钱的事务完成
sqlserver的话,在这个事务开始的时候,会给表数据加上共享锁(行,键,或者升级为表锁),根据你汇总数据的group by条件,如果是某些键,sqlserver可能会用到键锁,尽量只锁定你需要的这部分数据.
转账事务可以读取,但不能修改第一个事务放置了共享锁的数据.你13:10开始的转账事务会堵在那,直到13:20你的汇总钱的事务完成