ReZero's Utopia.

Mysql 45 讲

Word count: 629Reading time: 2 min
2021/01/01 Share

主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引 (clustered index)。

非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引 (secondary index)。

自增主键的插入数据模式,正符合了我们前面提到的递增插入的场景。每次插入 一条新记录,都是追加操作,都不涉及到挪动其他记录,也不会触发叶子节点的分裂

有没有什么场景适合用业务字段直接做主键的呢?还是有的。比如,有些业务的场景需求是
这样的:

  1. 只有一个索引;
  2. 该索引必须是唯一索引。

你一定看出来了,这就是典型的 KV 场景

我在上一篇文章末尾给你留下的问题是:如何避免长事务对业务的影响?
这个问题,我们可以从应用开发端和数据库端来看。

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

  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 这个工具不错,推荐使用;
  3. 在业务功能测试阶段要求输出所有的 general_log,分析日志行为提前发现问题;
  4. 如果使用的是 MySQL 5.6 或者更新版本,把 innodb_undo_tablespaces 设置成 2(或
    更大的值)。如果真的出现大事务导致回滚段过大,这样设置后清理起来更方便
CATALOG