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只是个概念,事务最终目的是要保障数据的可靠性,一致性。