47 MySQL运行时多个事务同时执行是什么场景?
通常而言,我们都是在业务系统里会开启事务来执行增删改操作的,举个例子,
@Transactional
public void doService(){
//增加一条数据
addUser();
//修改一条数据
updateUser();
//删除一条数据
deleteUser();
}
所以一般来说,业务系统是执行一个一个的事务,每个事务里可能是一个或者多个增删改查的SQL语句。
这个事务的概念想必不用我多说了,其实就是一个事务里的SQL要不然一起成功就提交了,要不然有一个SQL失败,那么事务就回滚了,所有SQL做的修改都撤销了!我们看下图。

接着问题来了,这个业务系统他可不是一个单线程系统啊!他是有很多线程的!
因为他面向的终端用户是有很多人的,可能会同时发起请求,所以他需要多个线程并发来处理多个请求的。
于是,这个业务系统很可能是基于多线程并发的对MySQL数据库去执行多个事务的!看下图。

那么每个事务里面的多个SQL语句都是如何执行的呢?
其实就是我们之前给大家讲过的那一套原理了,包括从磁盘加载数据页到buffer pool的缓存页里去,然后更新buffer pool里的缓存页,同时记录redo log和undo log,如下图所示。

每个事务如果提交了,那么就皆大欢喜,这个提交的过程我之前最早就讲过了,他有一些步骤,包括在redo log里记录事务提交标识之类的。
如果事务提交之后,redo log刷入磁盘,结果MySQL宕机了,是可以根据redo log恢复事务修改过的缓存数据的。
如果要回滚事务,那么就基于undo log来回滚就可以了,把之前对缓存页做的修改都给回滚了就可以了。
这就是在MySQL内核层面,把多个事务和我们之前讲解的buffer pool、redo log、undo log几个机制都结合在一起的一个场景讲解。想必大家都是可以理解的。
但是这里就有很多问题了
- 多个事务并发执行的时候,可能会同时对缓存页里的一行数据进行更新,这个冲突怎么处理?是否要加锁?
- 可能有的事务在对一行数据做更新,有的事务在查询这行数据,这里的冲突怎么处理?
所以接下来,我们要给大家讲解的,就是解决多个事务并发运行的时候,同时写和同时读写的一些并发冲突的处理机制,包括了MySQL事务的隔离级别、MVCC多版本隔离、锁机制,等等。