lealone / Lealone

比 MySQL 和 MongoDB 快10倍的 OLTP 关系数据库和文档数据库
Other
2.44k stars 513 forks source link

事务隔离级别问题 #133

Closed devqm closed 2 years ago

devqm commented 2 years ago

在repeatable_read模式下 设置手动提交事务,test表中5条数据。 步骤: 1.两个客户端分别开启一个事务 2.A客户端select test表 3.B客户端在test表中插入第6条数据,不提交事务 4.A客户端更新B客户端新增的数据(MySQL会等待一定时间如果B客户端没提交,就会锁超时),Lealone这边不会更新(受影响行数0) 5.A客户端select test表 6.AB客户端都提交事务 结果A客户端再次select * test表无法查询到新增数据,B客户端正常

image

image

devqm commented 2 years ago

Lealone是否会尽可能的兼容MySQL

codefollower commented 2 years ago

repeatable_read 模式下,A客户端是看不到B客户端 insert 但是未提交的记录的,如果看得到就变成读未提交级别了。

如果B客户端提交了,A客户端在原来的事务中更新B客户端 insert 的新记录,这个其实是幻读, 目前 lealone 对 repeatable_read 的实现更像是 snapshot 读。

sql 标准定义的 repeatable_read,确实有很多争议的地方。 事务隔离级别: REPEATABLE_READ 的瑕疵

codefollower commented 2 years ago

如果完全遵循 sql 标准对 repeatable_read 的定义,同时又避免更新丢失也是可以做到的。 就是在B客户端 insert 的新记录提交后,A客户端再次发出 select 语句能读到新记录(满足幻读), 如果B客户端 insert 的新记录提交后,A客户端发出的是 update/insert/delete 语句, 那么A客户端的当前事务要从 repeatable_read 级别自动转到 read_committed 级别, 这样才能避免B客户端的记录没有被丢失。

devqm commented 2 years ago

但是我没有操作第五步 5.A客户端select * test表,两边提交事务的话 A客户端是可以读到数据的,操作了第五步就会导致A客户端结束了事务仍然读不到新增的数据

codefollower commented 2 years ago

目前 lealone 对 repeatable_read 的实现更像是 snapshot,所以A客户端的当前事务看不到B客户端的任何操作,只有A客户端启动新事务后才看得到。我看看是否要完全遵循 sql 标准定义的有很多争议的 repeatable_read。

codefollower commented 2 years ago

sql 标准定义的那几个事务隔离级别大半是没啥用处的, 最有用的两个事务隔离级别是: read_committed 和 snapshot。

如果事务涉及各种更新语句,统一用 read_committed 最安全, 如果事务只查数据,用 snapshot 最省心。

不用去记什么幻读、更新丢失这种问题。

devqm commented 2 years ago

感谢 大概理解您的意思了