繁体   English   中英

对于长时间运行的报告,我是使用只读还是可序列化的事务?

[英]For a long running report, do I use a read only or serializable transaction?

我有一个用SQL * Plus编写的长期运行报告,带有几个SELECT。 我想更改事务隔离级别以获得对数据的一致视图。 我发现了两种可能的解决方

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET TRANSACTION READ ONLY;

我将哪一个用于报告?为什么? 任何性能影响? 对其他会话的任何影响(这是一个生产数据库)。

请注意,问题是关于上面的两个选项,而不是关于各种隔离级别。

SERIALIZABLE是否阻止对我的报告查询的表进行更改?

我天真地认为READ ONLY对数据库的压力稍微小一些,因为没有预期的数据变化。 这是真的,Oracle是否利用了这一点?

在Oracle中,您可以在SERIALIZABLEREAD COMMITTED之间进行选择。

READ ONLY与serializable相同,关于它看到其他会话更改的方式,但不允许表修改。

使用SERIALIZABLEREAD ONLY您的查询将无法在序列化事务开始后看到对数据库所做的更改。

使用READ COMMITTED ,您的查询将无法在查询的生命周期内看到对数据库所做的更改。

SERIALIZABLE       READ COMMITTED      ANOTHER SESSION
(or READ ONLY)


                                       Change 1
Transaction start  Transaction start
                                       Change 2
Query1 Start       Query1 Start
...                ...                 Change 3
Query1 End         Query1 End

Query2 Start       Query2 Start
...                ...                 Change 4
Query2 End         Query2 End

使用serializable,query1和query2只能看到change1。

使用read committed,query1将看到更改1和2,query2将看到更改1到3。

有趣的问题。 我相信SERIALIZABLEREAD ONLY对数据库具有相同的“税”,并且会比READ COMITTED (通常是默认值)更大。 您或其他并发用户不应存在显着的性能差异。 但是,如果数据库由于UNDO表空间太小或者undo_retention太短(默认值为15分钟)而无法保持读取一致性,那么查询将因臭名昭着的ORA-01555失败。 其他用户不应该经历痛苦,除非有其他用户尝试做类似的事情。 询问您的DBA设置的undo_retention参数是什么, UNDO表空间有多大以及它是否可自动扩展。

如果存在类似大小的非prod环境,请尝试使用不同的隔离级别对查询进行基准测试。 在第一个查询运行后检查数据库中的用户锁(或者如果您没有足够的权限,请检查DBA)。 多次进行此测试,每次测试具有不同的隔离级别。 基本上,文档很棒,但实验通常更快,更明确。

最后,为了彻底避开这个问题,你有没有办法将你的两个查询合并为一个,也许是一个UNION ALL 这在很大程度上取决于您的两个查询的关系。 如果是这样,那么问题就没有实际意义了。 一个组合查询将是自洽的。

..很多问题。

  1. 对于仅使用选择的会话,两个隔离级别都是等效的。 所以你选择哪一个并没有什么不同。 (READ只是不是ANSI标准)

  2. 除了性能影响之外,除非您在此会话中提交任何内容(仅限SERIALIZABLE),否则其他会话或具有事务隔离级别SERIALIZABLE或READ ONLY的会话内的其他会话不会产生任何影响。

  3. 您在这两个隔离级别内的选择性能不应该有所不同,因为您不在那里更改数据。

  4. 使用这两个隔离级别之一与Oracle默认READ COMMITTED进行比较的性能不是最佳的。 特别是如果在SERIALIZABLE交易期间大量数据发生变化,您可能会遇到性能下降。

  5. 我天真地认为READ ONLY对数据库的压力稍微小一些,因为没有预期的数据变化。 这是真的,Oracle是否利用了这一点?

    =>不。

希望这可以帮助。

Oracle文档中的这篇文章提供了很多关于不同事务隔离级别的详细信息。 http://docs.oracle.com/cd/B10501_01/server.920/a96524/c21cnsis.htm

在您的示例中,听起来您想要Serializable Oracle在读取数据时不会阻塞,因此在只读查询中使用serializable不应阻止其他事务中的查询或crud操作。

如其他答案中所述,使用read only隔离级别与使用可serializable类似,只是read only不允许插入,更新或删除。 但是,由于read only不是SQL标准并且可serializable ,所以我会在这种情况下使用serializable ,因为它应该完成同样的事情,将来很清楚其他开发人员,并且因为Oracle提供了更详细的文档,关于什么是与可serializable隔离级别的“幕后”一起使用。

以下是关于可序列化的一些信息,来自上面引用的文章(我在方括号中添加了一些注释以便澄清):

可序列化隔离模式通过防止幻像[读取来自其他事务的插入]和不可重复读取[读取来自其他事务的更新/删除]来提供更高的一致性,并且在读/写事务多次执行查询时可能很重要。

与可锁定块以进行读取和写入的其他可序列化隔离实现不同, Oracle提供非阻塞查询[非阻塞读取]和行级锁定的精细粒度,这两者都减少了写/写争用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM