首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >MySQL/InnoDB是否实现真正的可序列化隔离?

MySQL/InnoDB是否实现真正的可序列化隔离?
EN

Stack Overflow用户
提问于 2018-03-20 04:31:14
回答 2查看 0关注 0票数 0

不完全清楚MySQL文档InnoDB引擎是否实现真正可序列化的隔离_1或[_快照隔离]](...),这通常也被称为“可序列化”。是哪一个?

如果mysql InnoDB没有,是否有任何完全免费的、生产质量良好的RDBMS?

其中,“真正的可序列化隔离”不仅意味着没有按照sql标准读取异常,而且意味着没有写入倾斜异常,并将进一步详细解释。

EN

Stack Overflow用户

发布于 2018-03-20 12:35:13

最新情况:

请看评论,这似乎是修正了mysql 5.5,使用这些示例,我们仍然有一个表锁,索引下键锁不能被愚弄,AFAIK。

原件:

昨天发现了你的问题,我也在想关于InnoDb的MVCC可串行化模型。

所以我做了一些试验...。MySQL 5.1.37。中提供的可序列化问题的测试是一个很好的测试。PostgreSQL 9.0 MVCC文档,关于这一章系列化隔离与真实可序列化性

所以让我们在MySQL上测试它:

CREATE TABLE t1 (
 class integer,
 value integer
) ENGINE=InnoDB;

INSERT INTO t1 (`class`,`value`) VALUES
  (1,10),
  (1,20),
  (2,100),
  (2,200);

现在,我们将打开两个不同的连接,以具有两个并行事务(T1和T2):

T1:

SET TRANSACTIOn ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT SUM(value) FROM t1 WHERE class = 1;

结果是30。

T2:

 SET TRANSACTIOn ISOLATION LEVEL SERIALIZABLE;
 BEGIN;
 SELECT SUM(value) FROM t1 WHERE class = 2;

结果是300。

T1:

INSERT INTO t1 (`class`,`value`) VALUES (2,30);

=>等待

T2:

INSERT INTO t1 (`class`,`value`) VALUES (1,300);

==>Error 1213(40001):尝试锁定时发现死锁;尝试重新启动事务

T1现在成功插入,T2有回滚,良好的系列化性...

这将在PostgreSQL 9.0上失败(情况在9.1上正在改变,但这是另一个问题)。事实上只有1交易可以执行插入在桌子上。即使我们试图插入class=3和。

INSERT INTO t1 (`class`,`value`) VALUES (3,30);

我们会看到一个等待的锁,和死锁,以防出现问题。看起来我们在MySQL中有一个谓词锁..。但事实上在InnoDB中实施。

Innodb执行行锁,并在索引上锁定一些空白。在这里,我们没有索引在表上,看起来MySQL决定锁定表。

因此,让我们试着测试下一个键锁定,看看这是否强制序列化。首先回滚正在运行的事务(T1)。然后创建一个索引。

CREATE index t1class ON t1 (class);

现在重新做测试。成功,可序列化性仍然被强制执行。好消息。

但是随着索引的建立,我认为下一个键锁定和行锁都是在索引上完成的。这意味着,如果插入不影响并行事务,我们应该能够执行插入。现在出现了一个大问题...

T1:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT SUM(value) FROM t1 WHERE class = 1;

结果是30。

T2:

 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
 BEGIN;
 SELECT SUM(value) FROM t1 WHERE class = 2;

结果是300。

在这里,我们将在T1上做一个不相关的插入,现在我们有了一个索引,这将成功:

T1:

INSERT INTO t1 (`class`,`value`) VALUES (3,30);

两者都可以执行插入(这里我只做了一个),这是正常的。没有应用预测锁定,因此没有对class=3...。看起来,如果我们给下一个键锁定好的索引(插入时没有表锁),那么下一个键锁定的性能会更好。

现在,我们尝试在下一个键锁上插入T2(class=2)的行匹配选择:

T1:

INSERT INTO t1 (`class`,`value`) VALUES (2,30);

成功

T2:

INSERT INTO t1 (`class`,`value`) VALUES (1,300);

=>等待。

T1:

COMMIT;

T2:(在锁已消失的地方,就会插入)

SELECT SUM(value) FROM t1 WHERE class = 2;
COMMIT;

这里还有300个。看来可系列化已经消失了。

select * from t1;
+-------+-------+
| class | value |
+-------+-------+
|     1 |    10 | 
|     1 |    20 | 
|     2 |   100 | 
|     2 |   200 | 
|     3 |    30 | <-- test
|     2 |    30 | <-- from trans1
|     1 |   300 | <-- from trans2 ERROR!
+-------+-------+

结果:通过在插入影响并行事务查询的行之前插入一个新的无关行,我们欺骗了下一个键锁定机制。或者至少这是我从测试中了解到的。所以我想说,不要相信引擎具有真正的可序列化性。...。当你有集料在事务中,最好的方法是手动执行。把表锁上,把你的可序列化问题转化成一个真正的只有一个人的情况,没有惊喜!示例中的其他可串行化问题是约束验证(检查操作后的数量是否仍为正),你是否也拥有这些情况的锁。

票数 0
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100007685

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档