事务的四个特性
- 原子性:组成一个事务的多个数据库操作是一个不可分割的原子单元.
- 一致性:事务操作成功以后,数据库所处的状态和业务规则是一致的.
- 隔离性:并发操作数据时,不同事务拥有各自的数据空间,不会互相干扰.
- 持久性:事务提交以后,事务中的数据必须持久化到数据库中,不能因为数据库的崩溃导致数据的丢失.
保证事务四个特性的方法
数据库一般采用重执行日志保证原子性,一致性和持久性.重执行日志记录了数据库变化的每一个动作,数据库在执行事务的中途发生错误后,可以根据重执行日志来撤销已经提交的数据.已经提交的数据,数据库恢复以后也会根据日志对尚未持久化的数据进行相应的重执行操作.
隔离性通过数据库锁机制来保证.当多个事务试图同时对相同的数据进行操作时,只有持有锁的事务才能操作.类似Java中的同步阻塞状态.
高并发时,事务存在的问题
- 脏读:事务A读取到了事务B未提交的数据,当事务B回滚以后,事务A读取的数据就是脏数据.
- 不可重复读:事务A多次读取统一数据,事务B在事务A读取的过程中进行了修改并提交了事务,导致事务A多次读取的数据不一致.
- 幻读:当事务A进行数据修改时,事务B新增或删除了一条数据,导致事务A发现会有未修改的数据存在.
事务的四种隔离级别
事务隔离级别 |
脏读 |
不可重复读 |
幻读 |
读未提交(read-uncommitted) |
是 |
是 |
是 |
不可重复读(read-committed) |
否 |
是 |
是 |
可重复读(repeatable-read) |
否 |
否 |
是 |
串行化(serializable) |
否 |
否 |
否 |
事务隔离级别的实现原理
行级共享锁:S锁,多个事务对统一数据共享一把锁,都能读取数据,但是不能修改
行级排他锁:X锁,一个事务过去了一行数据的排他锁,其它事务就不能再获取该行数据的锁了,包括共享锁和排他锁.
- read-uncommitted:事务在读数据时不加锁,修改数据时对数据添加行级共享锁.
- read-committed:事务对当前读取的数据添加行级共享锁,读取完以后释放锁.事务再更新数据的瞬间添加行级排他锁,直到事务结束以后释放.
- repeatable-read:事务再读取数据时添加行级共享锁,事务结束才会释放锁.事务再更新数据的瞬间添加行级排他锁,直到事务结束以后释放.
- serializable:事务再读取数据时添加表级共享锁,直到事务结束释放.事务在修改数据时添加表级排他锁,直到事务结束释放.
MySQL事务隔离级别默认是repeatable-read,隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能影响越大