1、什么是事务
对于一个事务,要么事务内的SQL全部执行,要么都不执行
2、事务的四个特征
- 原子性
原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败。
begin transaction;
update account set money = money-100 where name = 'Brooks';
update account set money = money+100 where name = 'Cherry';
commit transaction;
- 一致性
数据库总是从一个一致性状态转换到另一个一致性状态。(事务按照预期生效,数据的状态是预期的状态)。举个例子:张三给李四转了100块钱,张三扣了100元,李四获得100元,数据状态是正确的为一致性,否者张三转帐了,李四却没有收到,数据错误,就没有达到一致性, - 隔离性
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。 - 持久性
一旦事务提交,则所做的修改就会永久保存在数据库中。无论什么情况数据也不会丢失。
3、MySQL四种隔离级别
- 读未提交 Read Uncommitted
在这个级别下,事务中的修改,即使没有提交,对其他事物也是可见的。可能会导致脏读,不可重复或幻读。 - 读提交 Read Committed
一个事务从开始到提交之前,所做的任何修改都是对其他事物不可见的。可能会发生幻读,不可重复读。 - Repeatable Read (MySQL默认隔离级别)
保证了同一个事物中多次读取同样的记录的结果是一致的,可能会发生幻读,InnoDB通过MVVC多并发版本控制来解决幻读问题。 - 串行化 Serializable
最高隔离级别。强制事物串行执行。避免幻读问题。SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超市和锁竞争问题。
4、什么是脏读,幻读,不可重复读?
- 脏读 Dirty Read (读未提交数据)
当事务A正在访问一个数据并进行了修改,但这种修改还没有提交到数据库中,此时事务B也访问到了这个数据,并且使用了这个数据。由于这个数据是还没有提交的数据,那么事务B读取的这个数据是“脏数据”,那么之后的操作都是不正确的。这种情况常发生于转账与取款操作中。 - 幻读 Phantom Read (前后多次读取,数据总量不一致)
当事务A执行读取操作时,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就想产生了幻觉一样,平白无故多了几条数据,称为幻读。 - 不可重复读 Unrepeatable Read (前后多次读取,数据内容不一致)
事务A在执行读取操作,由整个事务A比较大,前后读取同一条数据需要经历很长的时间 。而在事务A第一次读取数据,比如此时读取了小明的年龄为20岁,事务B执行更改操作,将小明的年龄更改为30岁,此时事务A第二次读取到小明的年龄时,发现其年龄是30岁,和之前的数据不一样了,也就是数据不重复了,系统不可以读取到重复的数据,成为不可重复读
5、事务是如何实现的?
首先让我们先来了解一下什么是事务日志
1、什么是redo log?
redo log叫做重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中。假设有个表叫做tb1(id,username) 现在要插入数据(3,ceshi):
redo log 有什么作用?
- mysql为了提升性能不会把每次的修改都实时同步到磁盘,而是会先存到Buffer Pool(缓冲池)里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。
- 那么问题来了,如果还没来的同步的时候宕机或断电了怎么办?还没来得及执行上面图中红色的操作。这样会导致丢部分已提交事务的修改信息!
- 所以引入了redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后在读取redo log恢复最新数据。
总结:redo log是用来恢复数据的 用于保障,已提交事务的持久化特性。
2、什么是undo log
undo log 叫做回滚日志,用于记录数据被修改前的信息。他正好跟前面所说的重做日志所记录的相反,重做日志记录数据被修改后的信息。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。
undo log 有什么作用?
undo log记录事务修改之前版本的数据信息,因此假如由于系统错误或者rollback操作而回滚的话可以根据undo log的信息来进行回滚到没被修改前的状态。
总结:undo log是用来回滚数据的用于保障未提交事务的原子性。
事务实现:
前面讲的重做日志,回滚日志以及锁技术就是实现事务的基础。
- 事务的原子性是通过 undo log 来实现的
- 事务的持久性性是通过 redo log 来实现的
- 事务的隔离性是通过 (读写锁+MVCC)来实现的
而事务的终极大 boss 一致性是通过原子性,持久性,隔离性来实现的。
原子性,持久性,隔离性折腾半天的目的也是为了保障数据的一致性!
总之,ACID只是个概念,事务最终目的是要保障数据的可靠性,一致性。