简体   繁体   English

是否有理由将数据库事务用于只读sql语句?

[英]Is there ever a reason to use a database transaction for read only sql statements?

As the question says, is there ever a reason to wrap read-only sql statements in a transaction? 如问题所述,是否有理由在事务中包装只读sql语句? Obviously updates require transactions. 显然,更新需要事务。

You still need a read-lock on the objects you operate on. 您仍然需要对要操作的对象进行读取锁定。 You want to have consistent reads, so writing the same records shouldn't be possible while you're reading them... 您希望获得一致的读取,因此在读取它们时不可能写相同的记录...

If you issue several SELECT statements in a single transaction, you will also produce several read-locks. 如果在单个事务中发出多个SELECT语句,则还将产生多个读取锁。

SQL Server has some good documentation on this (the "read-lock" is called shared lock, there): SQL Server对此有一些很好的文档(“读取锁”在此处称为共享锁):

http://msdn.microsoft.com/en-us/library/aa213039%28v=sql.80%29.aspx http://msdn.microsoft.com/en-us/library/aa213039%28v=sql.80%29.aspx

I'm sure MySQL works in similar ways 我确定MySQL的运作方式相似

Yes, if it's important that the data is consistent across the select statements run. 是的,如果跨选择语句运行的数据保持一致很重要。 For instance if you were getting the balance of several bank accounts for a user, you wouldn't want the balance values read to be inconsistent. 例如,如果您要为一个用户获取多个银行帐户的余额,则不希望余额值读取不一致。 Eg if this happened: 例如,如果发生这种情况:

With balance values B1=10 and B2=20 余额值为B1 = 10和B2 = 20

  1. Your code reads B1= 10. 您的代码读取为B1 = 10。
  2. Transaction TA1 starts on another DB client 事务TA1在另一个数据库客户端上启动
  3. TA1 writes B1 to 20, B2 to 10 TA1将B1写入20,B2写入10
  4. TA1 commits TA1提交
  5. Your code reads B2 = 10 您的代码读取B2 = 10

So you now think that B1 is 10 and B2 is 10, which could be displayed to the user and that says that $10 has disappeared! 因此,您现在认为B1是10,B2是10,这可能会显示给用户,并说$ 10消失了!

Transactions for reading will prevent this, since we would read B2 as 20 in step 5 (assuming a multiversioning concurrency control DB, which mysql+innodb is). 用于读取的事务将避免这种情况,因为在步骤5中我们将B2读为20(假设有一个多版本并发控制数据库,即mysql + innodb)。

MySQL 5.1, with the innodb engine has a default transaction isolation level which is REPEATABLE READS. 带有innodb引擎的MySQL 5.1具有默认的事务隔离级别,该级别是REPEATABLE READS。 So if you perform your SELECT inside a transaction no Dirty reads or Nonrepeatable reads can happen. 因此,如果在事务内执行SELECT,则不会发生脏读不可重复读 That means even with transaction commiting between two of your queries you'll always get a consistent database. 这意味着即使在两个查询之间提交事务,您也将始终获得一致的数据库。 In theory in REPEATABLE READS you couls only fear phantom reads , but with innodb this cannot even occurs. 从理论上讲,在REPEATABLE READS中,您可能只怕幻象读取 ,而对于innodb来说,这种情况甚至不会发生。 So by simply opening a Transaction you can assume database consistency (coherence) and perform as much select as you want without fearing parallel-running-and-ending write transactions. 因此,只需打开一个事务,就可以假定数据库的一致性 (一致性)并根据需要执行任意选择,而不必担心并行运行和结束写入事务。

Do you have any interest in having such a big consistency constraint? 您对拥有如此大的一致性约束感兴趣吗? Well it depends of what you're doing with your queries. 好吧,这取决于您对查询的处理方式。 having inconsistent reads means that if one of your query is based on a result from a previous one you may have problems: 读取结果不一致意味着,如果您的一个查询基于上一个查询的结果,则您可能会遇到以下问题:

  • if you're performing only one query you do not care, at all 如果您只执行一个查询,则根本不在乎
  • if none of your queries assumes a result from a previous one, do not care 如果您的任何查询都不假定来自上一个查询的结果,则不在乎
  • if you never re-read a record in the same session, same thing 如果您从未在同一会话中重新读取记录,那么
  • if you always read dependencies of your main record in the same query and do not use lazy loading, no problem 如果您始终在同一查询中读取主记录的依赖项,并且不使用延迟加载,则没问题
  • if a small inconsistency between your first and last query will not break your code, then forget about it. 如果您的第一个查询和最后一个查询之间的微小不一致不会破坏您的代码,那么就算了。 But be careful, this can make a very hard to debug application bug (and hard to reproduce). 但是要小心,这会使调试应用程序错误非常困难(并且很难重现)。 So get a robust application code, something which could maybe handle databases errors and crash nicely (or not even crash) when this occurs (2 time in one year?). 因此,获得了可靠的应用程序代码,它可能会处理数据库错误并在发生这种情况时(一年2次?)很好地崩溃(甚至不会崩溃)。
  • if you show critical data (I mean bank accounts and not blogs or chats), then you should maybe care about it 如果您显示关键数据 (我的意思是银行帐户,而不是博客或聊天记录),那么您可能应该关心它
  • if you have a lot of write operations , then you increase the risk of inconsistent reads, you may need to add transactions at least on some key points 如果您有很多写操作 ,那么您会增加读取不一致的风险,您可能至少需要在某些关键点添加事务
  • you may need to test impact on performances , having all read requests in transactions, when several write transactions are really altering the data, is certainly slowing the engine, he needs to handle several versions of the data. 您可能需要测试对性能的影响 ,在事务中拥有所有读取请求时,当多个写入事务确实在改变数据时,肯定会使引擎变慢,他需要处理多个版本的数据。 So you shoul dcheck if the impact is not too big for your application 因此,您应该检查对您的应用程序影响是否太大

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

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