一.事务
- 事务就是要保证一组数据库操作,要么全部成功,要么全部失败。
- MySQL中,事务支持是在引擎层实现。innoDB可以实现,但是MyISAM 引擎就不支持事务
二.隔离性与隔离级别
- ACID(Atomicity,Consistency,Isolation,Durability)原子性,一致性,隔离性。持久性。
- 读未提交:一个事务还没有提交时,他做的变更就能被别的事务看到、
- 读已提交:一个事务提交以后,他做的变更才会被其他事务看到。
- 可重复读: 一个事务执行过程中看到的数据,总是跟事务在启动时看到的数据时一致的。
- 串行化:对于同一条记录,''写'会加''写'锁,读会加读锁,当读写冲突后,访问的事务必须等前一个事务执行完成,才能继续执行。
脏读:当一个事务正在访问数据,并且对数据进行修改,这种修改没有提交到数据库中,这时另一个事务也访问这个数据,然后使用这个数据。 |
不可重复读:在一个事务中,多次读同一个数据,在这事务还没有结束时,另一个事务也访问该同一数据。那么第一个事务中的两次读数据之间,由于第二个事务的修改,第一个事务读到的数据可能是不一样的。 |
幻读:当一个事务查询一类数据时候,另一个事务对该类数据进行修改或删除操作,造成第一个事务前后两个表读取到的条数不一致。 |
丢失更新:第二个提交的事务将前一个事务给覆盖掉 |
三.不同隔离级别下导致不同结果
事务A | 事务B |
启动事务查询得到值1 | 启动事务 |
查询得道值1 | |
将1改成2 | |
查询得到值v1 | |
提交事务B | |
查询得到值v2 | |
提交事务A | |
查询得到值V3 |
读未提交:
V1的值就是2,这时候事务B虽然还未提交但是A可以看到。因此V2,V3也都是2;
读已提交:
V1是1,V2的值是2.事务B的更新再提交后才能被A看到。所以,V3的值也是2
可重复读 :
v1 ,v2是1,v3是2,因为v2还是1,遵循的就是,事务在执行期间看到的数据前后必须是一致的。
串行化
事务B执行将1改成2的时候就会被锁住,直到事务A提交后,事务B才可以继续执行,所以从
A角度看,V1,V2是1,V3的值是2。
数据库里面创建一个视图,访问的时候以视图的逻辑结果为准。
可重复读:
- 这个视图在事务启动创建时,整个事务存在期间都用这个视图
读已提交:
- 这个视图是在每个SQL语句开始执行的时候创建的
读未提交:
- 直接返回记录上的最新值,没有视图概念
串行化:
- 隔离级别下直接用加锁的方式来避免并行访问
四.mvvc(多版本数据并发控制)
基本思想:
- 每次事务生成的一个新版本本的数据,在读数据时选择不同版本的数据即可以实现对事务结果的完整性读取。
- MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,更好的方式处理 读写冲突,即使有读写冲突也不加锁,非阻塞并发读。
当前读
- 共享锁 ,select for update ,update, insert ,delete 这些操作都是一种当前读
- 读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取时还要保证其他并发事务不能修改当前记录,对读取的记录记性加锁。
快照读
- 不加锁的select操作就是快照读,即不加锁的非阻塞读,提高数据库的并发查询能力
- 快照读的前提是隔离级别不是串行化,串行级别的快照读会退化成当前读;
- 快照读的实现是基于多版本并发控制
MVVC解决的问题:
数据库要解决的三个问题
- 读读:不存在任何问题,也不需要并发控制
- 读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读。
- 写写:有线程安全问题,可能会存在更新丢失问题。
MVVC 是一种用来解决读写冲突的无锁并发访问,也就是为事务分配单项增长的时间戳,为每一个修改保存一个版本,版本于事务时间戳关联,读操作只读该事务开始前的数据库的快照
MVVC解决了以下问题:
- 读写操作不阻塞
- 解决读写操作带来的脏读,幻读,不可重复等事务隔离问题,但不能解决更新丢失问题。
mvvc的具体实现我一直没看懂。。。