赞
踩
mysql数据库默认的隔离级别是可重复读,但是这种事物控制不能解决幻读的问题,下面我们来看一下隔离级别支持情况:
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
读未提交 | 是 | 是 | 是 |
读已提交 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
串行化 | 否 | 否 | 否 |
事务的四个特性:ACID(原子性、一致性、隔离性和持久性)
设置 | 描述 |
---|---|
Serializable | 可避免脏读、不可重复读、虚读情况的发生。(串行化) |
Repeatable read | 可避免脏读、不可重复读情况的发生。(可重复读) |
Read committed | 可避免脏读情况发生(读已提交)。 |
Read uncommitted | 最低级别,以上情况均无法保证。(读未提交) |
在java的 Connection 方法,比如 setAutoCommit 或 setTransactionIsolation:
MVCC(multi-version-concurrent-control):MVCC即多版本并发控制,MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
MVCC就是由于事务的并发与隔离级别的存在,导致脏读,不可重复度,幻读等问题的一种解决策略。就是在操作数据的时候,比如进行增删改查的时候,mysql会在日志中把这个操作记录下来,同时生成版本信息,第一次操作版本为1,如果操作次数比较多,就会产生多个版本信息。然后这条记录还会在原来的数据基础上增加trx_id与db_roll_ptr,用来记录当前事务的id和上一条操作记录。当对同一条数据进行多次修改之后,这个日志就会形成一条日志链,而隔离级别的实现就是根据条件,读取某个对应版本的数据。它的实现原理主要是依赖记录中的隐式字段、undo日志、read view 来实现的。
隐式字段包括:
快照读和当前读
undo日志:
InnoDB把这些为了回滚而记录的这些东西称之为 undo log。值得注意的是,由于查询操作(SELECT)并不会修改任何用户记录,所以在查询操作时,并不需要记录相应的 undo log。
undo log 主要分为以下三种:
对 MVCC 有实质上帮助的是 update undo log,undo log 实际上就是存在于 rollback segment 中的旧纪录链。
readview:
ReadView就是事务在使用mvcc进行快照读操作时产生的读视图。该视图记录了一些信息去保证在后续判断中该读到那个版本的数据。
ReadView中主要包含4个比较重要的内容:
当生成了ReadView后,在通过mvcc访问某条记录时,按下边步骤来判断记录的那个版本是可见的:
当不能访问当前版本的数据时,就会顺着版本链找到历史版本进行判断。如果最后一个版本也不可见,那么查询结果就查不出该记录。
实际上mysql的select读有两种类型,分别是快照读与当前读。默认是快照读。快照读通过设置可重复读隔离级别即可解决幻读问题。当前读是一种对记录进行加锁的读类型。该锁分为读锁与写锁
简而言之:读读共享,读写互斥,写写互斥。另外,当前读因为获取了记录的锁,一样不会出现幻读问题
注意:两个事务是不可以同时update的,因为一执行update语句,就会获取该数据的写锁,直到事务被提交才会释放锁(如果不是事务操作,update语句执行完就会释放锁)。但是另外一个事务是可以通过快照读类型读数据的!(不获取读锁或者写锁就行)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。