并发效果可以被称为"行更新导致的丢失和双重读取"这里提到的https://msdn.microsoft.com/en-us/en-en/library/ms190805.aspx与Innodb引擎有关吗?
例如:
在READ UNCOMMITTED级别运行的事务不会发出共享锁,以防止其他事务修改当前事务读取的数据。在READ COMMITTED级别运行的事务会发出共享锁,但在读取行之后会释放行或页锁。在任何一种情况下,当您扫描索引时,如果另一个用户在您读取期间更改了该行的索引键列,则如果键更改将行移动到扫描前的位置,则该行可能会再次出现。同样,如果键更改将行移动到您已读取的索引中的某个位置,则可能不会显示该行。要避免这种情况,请使用SERIALIZABLE或HOLDLOCK提示或行版本控制
还有一个更新。从MSSQL引擎: " Microsoft SQL Server 2008内部"
在某些情况下,扫描最终可能会返回多次出现的行,甚至会跳过行。与索引顺序扫描相比,分配顺序扫描更容易出现此类行为。我将首先描述分配顺序扫描以及在何种情况下如何发生这种现象。然后我将解释索引顺序扫描会如何发生。分配顺序扫描图4-30分三步说明分配顺序扫描如何返回多次出现的行。步骤1显示正在进行的分配顺序扫描,以文件顺序(而不是索引顺序)读取某些索引的叶页。已经读取了两页(键50,60,70,80,10,20,30,40)。此时,在读取索引的第三页之前,有人使用键25在表中插入一行。步骤2显示在页面中发生的拆分,因为它已满,因此插入的目标。作为分割的结果,在我们的案例中稍后分配了一个新页面,在扫描尚未到达的位置。原始页面的一半行移动到新页面(键30,40),并且由于其键值,带有键25的新行被添加到原始页面。步骤3显示了扫描的继续:读取剩余的两个页面(键90,100,110,120,30,40),包括由于分割而添加的页面。请注意,第二次读取带有键30和40的行。
答案 0 :(得分:0)
在某些情况下,这可能与 InnoDB 引擎有关。
对于 InnoDB ,在SELECT
和READ COMMITTED
事务隔离级别中发出REPEATABLE READ
个查询,使用Consistent Read模式,这是一个实现MVCC,也称为乐观并发。在此模式下,读取查询不会发出任何锁定,而是引擎维护数据库的快照,就像查询开始时一样。在提交之前,该查询之外的任何更改都不可见(或者整个事务取决于选择了上述两个隔离级别中的哪一个)。
这种情况是否是您在问题中描述的情况是不可能的。
上面列出的MySQL手册部分的示例:
Session A Session B
SET autocommit=0; SET autocommit=0;
time
| SELECT * FROM t;
| empty set
| INSERT INTO t VALUES (1, 2);
|
v SELECT * FROM t;
empty set
COMMIT;
SELECT * FROM t;
empty set
COMMIT;
SELECT * FROM t;
---------------------
| 1 | 2 |
---------------------
1 row in set
读取READ UNCOMMITTED
事务隔离级别下发出的查询绕过MVCC和"参见"数据库中发生的所有事情,包括任何未提交的事务。这使得幻像和脏读成为一个问题。
依赖于显式使用锁(SELECT... FOR UPDATE
和SELECT... LOCK IN SHARED MODE
)或查询SERIALIZABLE
隔离级别下的查询会自动回退到基于锁定的并发性。后者将任何SELECT
查询升级为LOCK IN SHARED MODE
。在这种特殊情况下,您的问题中描述的数据移动是否安全取决于您使用的SELECT
查询WHERE
谓词。这会影响引擎是仅锁定刚刚读取的数据,还是锁定您读取的数据之间的整个范围。以下摘自the relevant manual page:
对于锁定读取(使用FOR UPDATE或LOCK IN SHARE MODE的SELECT),UPDATE和DELETE语句,锁定取决于语句是使用具有唯一搜索条件的唯一索引还是范围类型搜索条件。对于具有唯一搜索条件的唯一索引,InnoDB仅锁定找到的索引记录,而不是之前的间隙。对于其他搜索条件,InnoDB使用间隙锁或下一键(间隙加索引记录)锁来锁定扫描的索引范围,以阻止其他会话插入范围所覆盖的间隙。