一、事务有哪些特性
原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一个商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家中,消费者的钱也没花出去。
一致性(Consistency):是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户A和用户B在银行分别有800元和600元,总共1400元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。
隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?
1.持久性是通过 redo log (重做日志)来保证的;
2.原子性是通过 undo log(回滚日志) 来保证的;
3.隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
4.一致性则是通过持久性+原子性+隔离性来保证;
二、事务的隔离性
并发事务会引发什么问题?
MySQL 服务端是允许多个客户端连接的,这意味着 MySQL 会出现同时处理多个事务的情况。
那么在同时处理多个事务的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题。
脏读:读到其他事务未提交的数据;
不可重复读:前后读取的数据不一致;
幻读:前后读取的记录数量不一致。
SQL 标准提出了四种隔离级别来规避这些现象,隔离级别越高,性能效率就越低,这四个隔离级别如下:
读未提交(*read uncommitted*),指一个事务还没提交时,它做的变更就能被其他事务看到;
读提交(*read committed*),指一个事务提交之后,它做的变更才能被其他事务看到;
可重复读(*repeatable read*),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;
串行化(*serializable* );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;
(快照读)读已提交和可重复读是通过MVCC(多版本并发控制)方式来解决的。
Read View字段和记录中的字段对比来切换读取的不同版本的记录。可重复读是在事务启动后就一直用创建的Read View的版本,读取的数据不变。读已提交时在每次读取数据前都会重新创建一个Read View,在事务未提交之前读取的数据是以前版本,事务提交后版本更新,读取到的是新数据。
可重复读并没有彻底解决幻读的问题,避免幻读现象的发生
快照读(普通select)
当前读(select … for updata)加锁读