innodb 中的事务隔离级别学习
记得再多总是会忘,不如记下来。不仅可以分享让别人指出问题,还能在忘记的时候方便找到和补充。欢迎大家在下方留言,针对于基础知识,希望大家多多补充。
事务
事务主要用于处理一些复杂数据,保证数据的一致性。(不过现在在并发和数据一致性的问题上采用中间件redis
和 memcached
,不过因为 redis
姿势多并且其拥护多所以大部分项目都会在直接去考虑前者,甚至直接取代为数据库。)
- 在mysql 中只有innodb 存储引擎的数据库表才支持。
- 事务主要是用于管理 插入 删除修改 操作。
事务具有四个条件(ACID)
- 原子性(Atomicity,或称不可分割性)一个事务就是一个整体,一起死亡,一起成功,出错了回滚。在执行事务之前,先保存进度(undo log),出错就意味死亡回到事务执行前的状态。
- 持久性(Durability) 事务结束之后数据的修改是永久性的,mysql 中有一个缓冲池 读取数据时会先从缓存池中查找,如果没有再从磁盘中查找写入到缓冲池,再返回给你。(这里有个问题就是它的先后顺序,是先放入缓冲池中,再从缓冲池中返回,还是先放入缓冲池中,再把读取的数据返回,还是同时进行。当然还有缓冲池的数据更新也是一个需要学习的问题)
- 隔离性(Isolation,又称独立性)事务隔离可以分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable) 主要内容
- 一致性(Consistency)一致性就是实现数据的一致性,要做的这点就需要先保证上面三个条件没有问题,才能保证数据的一致性。
前提须知
脏读 dirty read
脏读 不名思意,脏的数据,因为事务可以回滚,只有事务完全提交之后,事务中执行的数据才是正确的数据。所以当事务一修改了数据,整好事务二读取到了。但是事务一进行了回滚,那么事务一读取到的数据就是无效。这个数据就是脏数据。
事务一 | 事务二 |
---|---|
update table set num =100 where id =1 | |
select name from where num =100 | |
commint | commint |
如果 事务一提交 则没有问题,但是如果是回滚 id =1 的name 就是脏数据。
幻读 Phantom Read
幻读 是指对于全表的数据,当你对全表数据修改的时候,中间插入了一条数据,就会发现有一条数据没有被修改。
不可重复读 NonRepeatable Read
前后读取数据不一致,当一个事务多次读取一个数据时,事务二进行了修改,那么在修改过后事务一读取数据时,会发现数据读取不一致的问题。
隔离级别
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
未提交读(Read uncommitted | 可能 | 可能 | 可能 |
已提交读(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
- 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据 ,不加任何锁
- 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
- 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
- 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞