数据库事务介绍
事务的四大特性(ACID)
1、A:原子性(atomicity):
事务的最小工作单元,要么全部成功,要么全部失败。
2、C:一致性(consistency):
事务开始和结束时,数据库的完整性不会被破坏。
3、I:隔离性(isolation):
不同事务之间互不影响,四种隔离级别为RU(读未提交)、RC(读已提交)、RR(可重复读)、Serializable(串行化)。
4、D:持久性(durability):
事务提交之后,对数据的修改是永久性的,即使系统故障也不会丢失。
事务的隔离级别
读未提交(Read Uncommitted/RU)
又称为脏读,一个事务可以读到另一个事务未提交的数据。这种隔离级别是最不安全的一种,因为未提交的事务存在回滚的情况。
读已提交(Read Committed/RC)
又称为不可重复读,一个事务在不同时间读取到了另一个事务已经提交的修改数据,导致在不同时间读到的同一条数据的结果不一样。
发生时间 | SessionA | SessionB |
---|---|---|
1 | begin | |
2 | select * from user where id=1;(张三) | |
3 | update user set name=‘李四’ where id=1;(默认隐式提交事务) | |
4 | select * from user where id=1;(李四) | |
5 | update user set name=‘王二’ where id=1;(默认隐式提交事务) | |
6 | select * from user where id=1;(王二) |
可重复读(Repeatable Read/RR)
又称为幻读,一个事务读可以读取到其他事务提交的数据,但是在RR隔离级别下,当前读取此条数据只可读取一次,在当前事务中,不论读取多少次,数据任然是第一次读取的值,不会因为在第一次读取之后,其他事务再修改提交此数据而产生改变。因此也成为幻读,因为读出来的数据并不一定就是最新的数据。
发生时间 | SessionA | SessionB |
---|---|---|
1 | begin | |
2 | select * from user where id=1;(张三) | |
3 | update user set name=‘李四’ where id=1;(默认隐式提交事务) | |
4 | select * from user where id=1;(张三) | |
5 | update user set name=‘王二’ where id=1;(默认隐式提交事务) | |
6 | select * from user where id=1;(张三) |
串行化(Serializable)
所有的数据库的读或者写操作都为串行执行,当前隔离级别下只支持单个请求同时执行,所有的操作都需要队列执行。这种隔离级别下所有的数据都是最稳定的,但是性能也是最差的。数据库的锁实现就是这种隔离级别的更小粒度版本。
数据丢失问题的解决
LBCC:基于锁的并发控制,Lock Based Concurrency Control
使用锁的机制,在当前事务需要对数据修改时,将当前事务加上锁,同一个时间只允许一条事务修改当前数据,其他事务必须等待锁释放之后才可以操作。
MVCC:多版本的并发控制,Multi-Version Concurrency Control
使用版本来控制并发情况下的数据问题,在B事务开始修改账户且事务未提交时,当A事务需要读取账户余额时,此时会读取到B事务修改操作之前的账户余额的副本数据,但是如果A事务需要修改账户余额数据就必须要等待B事务提交事务。
InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现的。一个保存了行的事务ID(DB_TRX_ID),一个保存了行的回滚指针(DB_ROLL_PT)。每开始一个新的事务,都会自动递增产 生一个新的事务id。事务开始时刻的会把事务id放到当前事务影响的行事务id中,当查询时需要用当前事务id和每行记录的事务id进行比较。