mysql的innodb通过nextkey lock解决了幻读,为什么还说默认隔离级别是可重复读?
一、解决了幻读,为什么还说默认隔离级别是可重复读
MySQL的可重复读隔离级别下是有“bug”的Snapshot Isolation,可以避免非write skew style的幻读,但还会有write skew异常(所有Snapshot Isolation的数据库都存在), 以及更新丢失异常(MySQL独有,由于MySQL的“bug”实现)。
一般意义上,“幻象(phantom)”可被定义为:对于相同的区间查询,插入和删除操作使得对相同的区间查询操作返回不同的结果。如果这么定义幻象异常,那么MVCC下的可重复读(RR)是可以避免幻象的。比如,PostgreSQL,在文档中就说,RR级别下可以避免幻读;MySQL也一样可以避免这种幻象(但我在官方文档中没找到)。
早期的数据库都是单版本的,这个定义没什么问题。但是,由于多版本的存在,情形就变得复杂了。RR隔离级别在MVCC实现的数据库中,一般会被实现成快照(SNAPSHOT),这就可能会产生另一种异常。由于事务会读到不同的版本,对于相同区间的查询,事务可能会错过某些满足该条件的并发地插入的记录,该事务只有在插入这条记录的事务提交后才能看到这条记录。进而产生的问题就是,事务本应该读到的数据,却没有被读到。
例如,assignments表有四列(eid, pid, workdate, hours)。assignments表示的是给employee(eid)分配project(pid),并记录某个工作日(workdate)的工时(hours)。限制每个工作日工时不超过8小时。
assign表示分配工时的存储过程,假设eid为1的员工已有两个project, 工时分别为4,1。有两个并发的事务T1, T2, 同时执行assign。当T1,T2开始时,对于满足条件eid = 1 and workdate = ‘2019.7.11’ 的元组,拿到的是相同的快照,它们都判定插入一条工时为4的元组不会使当日工时大于8。
这个异常不满足上面对幻读的定义,然而这个事务调度却是不正确的。一些文献把这种异常也称为幻象(write skew style phantom)[2]。
MVCC数据库无法避免这种异常。如果要避免这种异常,就必须要提高隔离级别到可串行化。可串行化的实现,在MySQL中是通过对读加锁(Gap Lock);在PG中是使用SSI算法,通过验证连续的RW依赖检测是否事务是否可串行化[3]。
第二,MySQL有一个比较特殊的情形,锁和快照读混用,这让它产生了另一种幻像。
如下面的例子,有两个事务,在RR隔离级别下, select是没有幻读的,但select for update却会产生幻读。因为select是读,通过时间戳读快照,事务2读不到事务1的写入。而select for update被认为是写,是可以更新已提交数据的,所以读到的是最新版本,事务2可以读到事务1的写入。PostgreSQL是没有这个现象的。
事务1 事务2 |
mysql> start transaction; mysql> start transaction; |
Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) |
mysql> select * from t; |
Empty set (0.00 sec) |
mysql> insert into t values(1); |
Query OK, 1 row affected (0.00 sec) |
mysql> commit; |
Query OK, 0 rows affected (0.01 sec) |
// no phantom |
mysql> select * from t; |
Empty set (0.00 sec) |
// phantom |
mysql> select * from t for update; |
+——+ |
| c | |
+——+ |
| 1 | |
+——+ |
1 row in set (0.00 sec) |
// update committed row |
mysql> update t set c=2; |
Query OK, 0 rows affected (0.00 sec) |
Rows matched: 1 Changed: 0 Warnings: 0 |
mysql> commit; |
Query OK, 0 rows affected (0.01 sec) |
延伸阅读:
二、什么是数据库
有组织且相互关联的数据的集合称为数据库。database 是一个存储数据的应用程序。它有各种应用程序,包括 MySQL、Microsoft SQL、Oracle 等。
每个数据库都不同,因为每个公司/组织都有其结构、数据类型和约束。数据库 会定期更新,以获取有关公司的最新数据。
数据库可以手动和数字方式维护。在这个数据无处不在的时代,数字数据库是优选和使用。数据库的大小取决于组织的数据和需求。
数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。

猜你喜欢LIKE
相关推荐HOT
更多>>
redis怎么实现数据库类似rank并列排名?
一、redis实现数据库类似rank并列排名的方法Sorted Set是一个有序的集合,其中的每个成员都会被赋予一个分数(score),通过对分数的操作可以实...详情>>
2023-10-15 17:23:44
Oracle怎么修改某个字段特定位置的字符?
一、Oracle修改某个字段特定位置的字符的方法1、查找需要修改的记录“查找需要修改的记录是指在数据库中定位需要进行修改的数据行。在进行数据...详情>>
2023-10-15 16:30:30
腾讯星图(Star Knowledge Graph)是什么样的数据库?
一、腾讯星图(Star Knowledge Graph)是什么样的数据库腾讯星图(Star Knowledge Graph,即SKG,也称知识图谱),是一个图数据库和图计算引擎...详情>>
2023-10-15 16:06:16
Python线程为什么搞个setDaemon?
一、Python线程为什么搞个setDaemon当启动一个线程时设置thread.setDaemon(True),则该线程为守护线程(也可以称为后台线程)。表示该线程是不...详情>>
2023-10-15 10:34:46热门推荐
为什么微服务一定要上Docker?
沸怎样用SQL语句实现查找一列中第N大值?
热什么是云访问安全代理(CASB)?
热MYSQL 查询库存结存数量语句怎么写?
新VUE使用什么连接并搭建搭建本地数据库?
超级APP系统比市场APP系统有哪些亮点呢?
哪些平台支持Python编程?
mysql有排他锁为什么还需要共享锁呢?
为什么搜索引擎在磁盘上的索引不能做到实时添加而数据库可以?
设置数据库的字符集和设置表字段字符集的区别是什么?
windows版oracle为什么老是卸载不干净?
redis怎么实现数据库类似rank并列排名?
sql server2000导出CSV文件用EXCEL数据格式出错怎么处理?
Oracle怎么修改某个字段特定位置的字符?
技术干货






