2012-12-18 68 views
4

假如我这样做(注:下面的语法可能是不正确的,但不要担心......它只是在那里做出点)做数据库事务防止其他用户干扰它

Start Transaction 
INSERT INTO table (id, data) VALUES (100,20), (100,30); 
SELECT * FROM table WHERE id = 100; 
End Transaction 

因此,选择的目标是从刚刚插入前一个插入表的所有信息以及之前的INSERT中插入...

现在假设在执行期间,INSERT执行后,某些其他用户也执行ID = 100的INSERT ...

事务的下一步中的SELECT语句是否也会获得由其他用户执行的INSERT插入的行,还是只会得到事务内前一个INSERT插入的两行?

顺便说一句,我使用的是MySQL,所以请调整你的答案到MySQL

回答

6

这完全取决于数据库连接使用的事务隔离。

根据MySQL 5.0 Certification Study Guide

enter image description here

页420描述了隔离级别

  • 脏读是读通过的另一做出提交的修改一个事务处理3个交易条件。假设事务T1修改一行。如果事务T2读取行并且看到修改,尽管T1还没有提交,那就是脏读。这是一个问题的原因之一是,如果T1回滚,更改被撤消,但T2不知道。
  • 当事务执行两次相同的检索,但每次都得到不同的结果时,将发生不可重复的读取。假设T1读取一些行,然后T2更改其中一些行并提交更改。如果T1在再次读取行时看到更改,则会得到不同的结果;最初的阅读是不可重复的。这是一个问题,因为T1没有从同一个查询得到一致的结果。
  • 幻影是出现在以前不可见的地方的行。假设T1和T2开始,T1读取一些行。如果T2插入新的并且T1再次读取时看到该行,则该行是幻影。

页421描述了四个(4)事务隔离级别:

  • READ-UNCOMMITTED:允许一个事务看到其他事务做出提交的更改。此隔离级别允许发生脏读,不可重复读取和幻像。
  • READ-COMMITTED:允许交易查看由其他交易所做的更改,仅当他们已经提交时。未提交的更改仍然不可见。这个隔离级别允许不可重复的读取和幻像发生。
  • REPEATABLE READ(默认值):确保事务发出两次相同的SELECT,无论其他事务提交或未提交的更改如何,它都会获得相同的结果。换句话说,它从相同查询的不同执行中获得一致的结果。在某些数据库系统中,REPEATABLE READ隔离级别允许幻影,如果另一个事务插入新行,则在SELECT语句之间的第二个SELECT中将看到它们。 InnoDB不是这样; REPEATABLE READ级别不出现幻影。
  • SERIALIZABLE:完全隔离一个交易与其他交易的影响。它与REPEATABLE READ相似,但有一个限制:一个事务选择的行不能被另一个事务更改,直到第一个事务完成。

隔离级别可以为您的数据库会话全局设置,您的会话中,或特定的交易:

SET GLOBAL TRANSACTION ISOLATION LEVEL isolation_level; 
SET SESSION TRANSACTION ISOLATION LEVEL isolation_level; 
SET TRANSACTION ISOLATION LEVEL isolation_level; 

其中ISOLATION_LEVEL是以下值之一:

  • 'READ UNCOMMITTED'
  • 'READ COMMITTED'
  • 'REPEATABLE READ'
  • 'SERIALIZABLE'

my.cnf您可以设置默认的还有:

[mysqld] 
transaction-isolation = READ-COMMITTED 
0

该交易将使它看起来像在交易中的语句,而不必与其他事务的任何干扰运行。大多数DBMS(包括MySQL)为事务维护ACID属性。在你的情况下,你对A for Atomic感兴趣,这意味着DBMS将使你的交易中的所有语句看起来像原子一样无中断地运行。

2

当其他用户正在更新同一行时,将应用行级别锁定。所以他只能在交易结束后才能进行更改。所以你会看到你插入的结果集。希望这可以帮助。

0

只有需要访问表中相同行的用户才能生效。否则用户不会受到影响。

但是,它稍微复杂一点,因为行锁定可以是读锁定或写锁定。

以下是InnoDB存储引擎的说明。

2

干扰对于SQL数据库事务来说是一个模糊的词。交易可以看到的行数部分由其isolation level决定。

因此,选择的目标是获得来自 刚刚通过前面的插入和仅由前 INSERT插入表中的所有信息...

前段插入是也有点模糊。

可能应该在之前提交插入问题您尝试读取它。否则,在您控制的某些条件下而不是,该事务可能会回滚,并且ID = 100的行可能实际上不存在。

当然,承诺之后,其他交易可以自由更改“id”,“value”或两者的值。 (如果他们有足够的权限,那就是)。

0

出于效率原因,开发人员不会将事务设置为完全相互隔离。 数据库支持倍数isolation级别,即可串行化,可重复读取,已提交读取和未提交读取。他们从最严格到最不严格的清单。

相关问题