简体   繁体   English

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

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

I have a long running report written in SQL*Plus with a couple of SELECTs. 我有一个用SQL * Plus编写的长期运行报告,带有几个SELECT。 I'd like to change the transaction isolation level to get a consistent view on the data. 我想更改事务隔离级别以获得对数据的一致视图。 I found two possible solutions: 我发现了两种可能的解决方

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

and

SET TRANSACTION READ ONLY;

Which one do I use for a report and why? 我将哪一个用于报告?为什么? Any performance implications? 任何性能影响? Any implications on other sessions (this is a production database). 对其他会话的任何影响(这是一个生产数据库)。

Please note that the question is specifically about the two options above, not about the various isolation levels. 请注意,问题是关于上面的两个选项,而不是关于各种隔离级别。

Does SERIALIZABLE blocks changes to a table that is queried for my report? SERIALIZABLE是否阻止对我的报告查询的表进行更改?

I would naively assume that READ ONLY is a little bit less stressful for the database, as there are no data changes to be expected. 我天真地认为READ ONLY对数据库的压力稍微小一些,因为没有预期的数据变化。 Is this true, does Oracle take advantage of that? 这是真的,Oracle是否利用了这一点?

In Oracle, you can really choose between SERIALIZABLE and READ COMMITTED . 在Oracle中,您可以在SERIALIZABLEREAD COMMITTED之间进行选择。

READ ONLY is the same as serializable, in regard to the way it sees other sessions' changes, with the exception it does not allow table modifications. READ ONLY与serializable相同,关于它看到其他会话更改的方式,但不允许表修改。

With SERIALIZABLE or READ ONLY your queries won't see the changes made to the database after your serializable transaction had begun. 使用SERIALIZABLEREAD ONLY您的查询将无法在序列化事务开始后看到对数据库所做的更改。

With READ COMMITTED , your queries won't see the changes made to the database during the queries' lifetime. 使用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

With serializable, query1 and query2 will only see change1. 使用serializable,query1和query2只能看到change1。

With read committed, query1 will see changes 1 and 2, and query2 will see changes 1 through 3. 使用read committed,query1将看到更改1和2,query2将看到更改1到3。

Interesting question. 有趣的问题。 I believe that SERIALIZABLE and READ ONLY would have the same "tax" on the database, and would be greater than that of READ COMITTED (usually the default). 我相信SERIALIZABLEREAD ONLY对数据库具有相同的“税”,并且会比READ COMITTED (通常是默认值)更大。 There shouldn't be a significant performance difference to you or other concurrent users. 您或其他并发用户不应存在显着的性能差异。 However, if the database can't maintain your read consistency due to too small of UNDO tablespace or too short undo_retention (default is 15 minutes), then your query will fail with the infamous ORA-01555 . 但是,如果数据库由于UNDO表空间太小或者undo_retention太短(默认值为15分钟)而无法保持读取一致性,那么查询将因臭名昭着的ORA-01555失败。 Other users shouldn't experience pain, unless there are other users trying to do something similar. 其他用户不应该经历痛苦,除非有其他用户尝试做类似的事情。 Ask your DBA what the undo_retention parameter is set at and how big the UNDO tablespace and whether or not it's autoextensible. 询问您的DBA设置的undo_retention参数是什么, UNDO表空间有多大以及它是否可自动扩展。

If there's a similarly sized non-prod environment, try benchmarking your queries with different isolation levels. 如果存在类似大小的非prod环境,请尝试使用不同的隔离级别对查询进行基准测试。 Check the database for user locks after the 1st query runs (or have your DBA check if you don't have enough privileges). 在第一个查询运行后检查数据库中的用户锁(或者如果您没有足够的权限,请检查DBA)。 Do this test several times, each with different isolation levels. 多次进行此测试,每次测试具有不同的隔离级别。 Basically, documentation is great, but an experiment is often quicker and unequivocal. 基本上,文档很棒,但实验通常更快,更明确。

Finally, to dodge the issue completely, is there any way you could combine your two queries into one, perhaps with a UNION ALL ? 最后,为了彻底避开这个问题,你有没有办法将你的两个查询合并为一个,也许是一个UNION ALL This depends largely on the relationship of your two queries. 这在很大程度上取决于您的两个查询的关系。 If so, then the question becomes moot. 如果是这样,那么问题就没有实际意义了。 The one combined query would be self-consistent. 一个组合查询将是自洽的。

.. a lot of questions. ..很多问题。

  1. Both isolation levels are equivalent for sessions that only use selects. 对于仅使用选择的会话,两个隔离级别都是等效的。 So it does not make a difference which one you choose. 所以你选择哪一个并没有什么不同。 (READ ONLY is not a ANSI Standard) (READ只是不是ANSI标准)

  2. Except performance influences, there are no implications from other sessions or to other sessions inside a session with transaction isolation level SERIALIZABLE or READ ONLY, unless you commit anything in this session (SERIALIZABLE only). 除了性能影响之外,除非您在此会话中提交任何内容(仅限SERIALIZABLE),否则其他会话或具有事务隔离级别SERIALIZABLE或READ ONLY的会话内的其他会话不会产生任何影响。

  3. Performance of your select inside these two isolation levels should not differ because you don't change data there. 您在这两个隔离级别内的选择性能不应该有所不同,因为您不在那里更改数据。

  4. Performance using one of these two isolation levels compared against Oracle default READ COMMITTED is not optimal. 使用这两个隔离级别之一与Oracle默认READ COMMITTED进行比较的性能不是最佳的。 Especially if a lot of data is changing during your SERIALIZABLE transaction, you can expect a performance downside. 特别是如果在SERIALIZABLE交易期间大量数据发生变化,您可能会遇到性能下降。

  5. I would naively assume that READ ONLY is a little bit less stressful for the database, as there are no data changes to be expected. 我天真地认为READ ONLY对数据库的压力稍微小一些,因为没有预期的数据变化。 Is this true, does Oracle take advantage of that? 这是真的,Oracle是否利用了这一点?

    => No. =>不。

hope this helps. 希望这可以帮助。

This article from the Oracle documentation gives a lot of detailed info about the different transaction isolation levels. Oracle文档中的这篇文章提供了很多关于不同事务隔离级别的详细信息。 http://docs.oracle.com/cd/B10501_01/server.920/a96524/c21cnsis.htm http://docs.oracle.com/cd/B10501_01/server.920/a96524/c21cnsis.htm

In your example, it sounds like you are wanting Serializable . 在您的示例中,听起来您想要Serializable Oracle does not block when reading data, so using serializable in your read-only query should not block queries or crud operations in other transactions. Oracle在读取数据时不会阻塞,因此在只读查询中使用serializable不应阻止其他事务中的查询或crud操作。

As mentioned in other answers, using the read only isolation level is similar to using serializable , except that read only does not allow inserts, updates, or deletes. 如其他答案中所述,使用read only隔离级别与使用可serializable类似,只是read only不允许插入,更新或删除。 However, since read only is not an SQL standard and serializable is, then I would use serializable in this situation since it should accomplish the same thing, will be clear for other developers in the future, and because Oracle provides more detailed documentation about what is going with "behind the scenes" with the serializable isolation level. 但是,由于read only不是SQL标准并且可serializable ,所以我会在这种情况下使用serializable ,因为它应该完成同样的事情,将来很清楚其他开发人员,并且因为Oracle提供了更详细的文档,关于什么是与可serializable隔离级别的“幕后”一起使用。

Here is some info about serializable, from the article referenced above (I added some comments in square brackets for clarification): 以下是关于可序列化的一些信息,来自上面引用的文章(我在方括号中添加了一些注释以便澄清):

Serializable isolation mode provides somewhat more consistency by protecting against phantoms [reading inserts from other transactions] and nonrepeatable reads [reading updates/deletes from other transactions] and can be important where a read/write transaction executes a query more than once. 可序列化隔离模式通过防止幻像[读取来自其他事务的插入]和不可重复读取[读取来自其他事务的更新/删除]来提供更高的一致性,并且在读/写事务多次执行查询时可能很重要。

Unlike other implementations of serializable isolation, which lock blocks for read as well as write, Oracle provides nonblocking queries [non-blocking reads] and the fine granularity of row-level locking, both of which reduce write/write contention. 与可锁定块以进行读取和写入的其他可序列化隔离实现不同, Oracle提供非阻塞查询[非阻塞读取]和行级锁定的精细粒度,这两者都减少了写/写争用。

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

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