MySQL 面试题:事务

设置事务隔离级别的理由?

在性能和并发影响之间做个平衡。

MySQL 的事务隔离级别有哪几种,并发时不同的级别会造成哪些影响?

  • 如果一个事务读到了另一个未提交事务修改过的数据,那就意味着发生了脏读。
  • 如果一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值,那就意味着发生了不可重复读。
  • 如果一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来,那就意味着发生了幻读。(mysql 的 rr 一定程度解决了幻读)

介绍一下 MVCC 。

所谓的 MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用 READ COMMITTED、REPEATABLE READ 这两种隔离级别的事务在执行普通的 SELECT 操作时访问记录的版本链的过程,这样子可以使不同事务的读-写、写-读操作并发执行,从而提升系统性能。READ COMMITTED、REPEATABLE READ 这两个隔离级别的一个很大不同就是:生成 ReadView 的时机不同,READ COMMITTED 在每一次进行普通 SELECT 操作前都会生成一个 ReadView,而 REPEATABLE READ 只在第一次进行普通 SELECT 操作前生成一个 ReadView,之后的查询操作都重复使用这个 ReadView 就好了。

如何避免长事务对业务的影响?

首先,从应用开发端来看:

  1. 确认是否使用了 set autocommit=0。这个确认工作可以在测试环境中开展,把 MySQL 的 general_log 开起来,然后随便跑一个业务逻辑,通过 general_log 的日志来确认。一般框架如果会设置这个值,也就会提供参数来控制行为,你的目标就是把它改成 1。
  2. 确认是否有不必要的只读事务。有些框架会习惯不管什么语句先用 begin/commit 框起来。我见过有些是业务并没有这个需要,但是也把好几个 select 语句放到了事务中。这种只读事务可以去掉。
  3. 业务连接数据库的时候,根据业务本身的预估,通过 SET MAX_EXECUTION_TIME 命令,来控制每个语句执行的最长时间,避免单个语句意外执行太长时间。

其次,从数据库端来看:

  1. 监控 information_schema.Innodb_trx 表,设置长事务阈值,超过就报警 / 或者 kill;
  2. Percona 的 pt-kill 这个工具不错,推荐使用;在业务功能测试阶段要求输出所有的 general_log,分析日志行为提前发现问题;
  3. 如果使用的是 MySQL 5.6 或者更新版本,把 innodb_undo_tablespaces 设置成 2(或更大的值)。如果真的出现大事务导致回滚段过大,这样设置后清理起来更方便。
posted @ 2022-04-05 21:52  profound-wu  阅读(81)  评论(0)    收藏  举报