一.数据库事务
1. 定义
数据库事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。
2. 典型特性
典型特性有原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durabilily),简称ACID。

原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性:指在事务开始之前和事务结束以后,数据不会被破坏,假如 A 账户给 B 账户转 10 块钱,不管成功与否,A 和 B 的总金额是不变的。
隔离性:多个事务并发访问时,事务之间是相互隔离的,即一个事务不影响其它事务运行效果。简言之,就是事务之间是井水不犯河水的。
持久性:表示事务完成以后,该事务对数据库所做的更改操作将持久地被保存在数据库中。
二.事务的实现原理
1. 事务日志
InnoDB 事务日志包括 redo log(重做日志)和 undo log(回滚日志)。
redo log(重做日志)
通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行的修改,用来实现 事务的持久性 。
该日志文件主要由两部分组成:重做日志缓冲(redo log buffer)和重做日志文件(redo log),前者存储在内存中,后者存储在磁盘中。

mysql 为了提升性能,不会把每次的修改都实时同步到磁盘,而是会先存到 Buffer Pool(缓冲池) 里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。
那么问题来了,如果还没来的同步的时候宕机或断电了怎么办?还没来得及执行上面图中红色的操作,这样会丢失部分已提交事务的修改信息。
所以引入了redo log来记录已成功提交事务的修改信息,并且会把redo log持久化到磁盘,系统重启之后再读取redo log来恢复最新的数据。
undo log(回滚日志)
redo log(重做日志)记录的是数据被修改后的信息,而undo log(回滚日志)跟redo log(重做日志)所记录的相反,是用于记录数据被修改前的信息。
undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。
每次写入数据或者修改数据之前都会把修改前的信息记录到 undo log,undo log 记录事务修改之前版本的数据信息。
可以这样认为,当 delete 一条记录时,undo log 中会记录一条对应的 insert 记录,当 update 一条记录时,它记录一条对应相反的 update 记录。
因此假如由于系统错误或者rollback操作而回滚的话,可以根据undo log的信息来进行回滚到没被修改前的状态,所以undo log用于保障 未提交事务的原子性 。
2. mysql锁技术以及MVCC基础
mysql锁技术
当有多个请求来读取表中的数据时,可以不采取任何操作,但是多个请求里有读请求,又有修改请求时,就必须有一种措施来进行并发控制,不然很有可能会造成数据的不一致。
解决上述问题很简单,只需用两种锁的组合:“读写锁”,来对读写请求进行控制,读写锁包含 共享锁(shared lock) 和 排他锁(exclusive lock) 。
共享锁 (shared lock),又叫做 “读锁” ,是可以共享的,或者说多个读请求可以共享一把锁读数据,不会造成阻塞。
排他锁 (exclusive lock),又叫做 “写锁”,会排斥其他所有获取锁的请求,一直阻塞,直到写入完成释放锁。

通过读写锁,可以做到读读可以并行,但是不能做到写读,写写并行,事务的 隔离性 就是根据读写锁来实现的。
MVCC基础
MVCC (MultiVersion Concurrency Control) 叫做多版本并发控制。
InnoDB的 MVCC ,是通过在每行记录的后面保存两个隐藏的列来实现的。这两个列, 一个保存了行的创建时间,一个保存了行的过期时间, 当然存储的并不是实际的时间值,而是系统版本号。
MVCC的主要实现思想是通过数据多版本来做到读写分离,从而实现不加锁读,进而做到读写并行。
MVCC在mysql中的实现依赖的是undo log与read view,undo log 记录某行数据的多个版本的数据;而read view 用来判断当前版本数据的可见性。
3. 事务的实现
重做日志,回滚日志以及锁技术就是实现事务的基础。
事务的 原子性 是通过 undo log 来实现的;
事务的 持久性 是通过 redo log 来实现的;
事务的 隔离性 是通过 (读写锁+MVCC)来实现的;
事务的 一致性 是通过原子性,持久性,隔离性来共同实现的。
总之,ACID只是个概念,原子性,持久性,隔离性都是为了实现数据的一致性,事务的最终目的就是要保障数据的一致性。