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 的回答

4

6 回答 6

7

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

根据MySQL 5.0 认证学习指南

在此处输入图像描述

第 420 页描述了由隔离级别处理的三个事务条件

  • 脏读是一个事务读取另一个事务未提交的更改。假设事务 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 语句之间的 inerbal 中,第二个 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
于 2012-12-18T19:08:55.307 回答
2

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

于 2012-12-18T17:22:39.643 回答
2

当涉及到 SQL 数据库事务时,干扰是一个模糊的词。事务可以看到的行部分取决于其隔离级别

因此,选择的目标是从表中获取所有信息,这些信息刚刚被前面的插入插入并且只被前面的 INSERT...

前面的插入也有点模糊。

可能应该在尝试阅读之前提交有问题的插入。否则,在某些不受您控制的情况下,该事务可能会回滚,并且 id=100 的行可能实际上不存在。

当然,在它提交之后,其他事务可以自由地更改“id”、“value”的值,或两者兼而有之。(如果他们有足够的权限,那就是。)

于 2012-12-18T17:42:07.830 回答
0

该事务将使事务中的语句看起来像是在不受其他事务干扰的情况下运行。大多数 DBMS(包括 MySQL)维护事务的ACID属性。在您的情况下,您对 A for Atomic 感兴趣,这意味着 DBMS 将使您的事务中的所有语句看起来都以原子方式运行而不会中断。

于 2012-12-18T17:20:34.440 回答
0

唯一生效的用户是那些需要访问表中相同行的用户。否则用户不会受到影响。

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

这是对InnoDB存储引擎的解释。

于 2012-12-18T17:29:39.077 回答
0

出于效率原因,开发人员不会将事务设置为彼此完全隔离。数据库支持多个隔离级别,即可序列化、可重复读取、已提交读和未提交读。它们是从最严格到最不严格的列表。

于 2012-12-18T17:56:04.107 回答