事务的基本要素(ACID):
原子性:一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。实现事务的原子性,要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。
一致性:数据库总是从一个一致的状态转换到另一个一致状态(以转钱为例)
隔离性:并发事务之间互相影响的程度,比如一个事务会不会读取到另一个未提交的事务修改的数据
持久性: 事务提交后,对系统的影响是永久的
事务的并发问题:
脏读:当前事务看到了别的事务未提交的数据(侧重点在于别的事务未提交)
不可重复读:不可重复读的侧重点在于更新修改数据。表示在同一事务中,查询相同的数据源时,其结果不一致 例如:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
幻读:幻读的侧重点在于新增和删除。表示在同一个事务中,使用相同的查询语句,第二次查询时,莫名的多出了一些之前不存在的数据(或者莫名的少了一些数据) 例如:A将数据库中所有学生的分数改为ABCDE等级,但是B就在此时插入了一条分数的记录。当A修改结束后发现这条新增的没有改过来,就好像发生了幻觉一样
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
MySQL的四种事务隔离级别(默认为可重复读-RR)
读未提交(read-uncommitted) :隔离级别:0. 可以读取未提交的记录。会出现脏读。
不可重复读(read-committed ):隔离级别:1. 事务中只能看到已提交的修改。不可重复读,会出现幻读。该隔离级别是大多数数据库系统的默认隔离级别,但是MySQL的则是RR。
可重复读 (repeatable-read):隔离级别:2. 通过Next-key lock(行锁和间隙锁)和mvcc机制来解决部分幻读问题。
可串行化(serializable):隔离级别:3. 该隔离级别会在读取的每一行数据上都加上锁,退化为基于锁的并发控制,即LBCC
注意:
1、事务隔离级别为读未提交时,写数据只会锁住相应的行
2、事务隔离级别必须为可重复读,如果检索条件有索引(包括主键索引)的时候,默认加锁方式是Next-key lock(行锁和间隙锁);如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读。
3、事务隔离级别为串行化时,读写数据都会锁住整张表
4、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。