龙空技术网

MYSQL存储引擎InnoDB(七十三):在线DDL性能和并发

泡泡研究笔记 158

前言:

此时咱们对“mysql在线ddl不锁表”可能比较着重,各位老铁们都想要分析一些“mysql在线ddl不锁表”的相关资讯。那么小编在网上收集了一些有关“mysql在线ddl不锁表””的相关内容,希望你们能喜欢,姐妹们快快来学习一下吧!

Online DDL 改进了 MySQL 操作的几个方面:

1、访问表的应用程序响应速度更快,因为在 DDL 操作进行时,可以对表进行查询和 DML 操作。减少锁定和等待 MySQL 服务器资源会带来更大的可伸缩性,即使对于不参与 DDL 操作的操作也是如此。

2、即时操作仅修改数据字典中的元数据。在操作的执行阶段,可能会短暂地对表进行独占元数据锁定。表数据不受影响,使操作瞬间完成。允许并发 DML。

3、联机操作避免了与表复制方法相关的磁盘 I/O 和 CPU 周期,从而最大限度地减少了数据库的整体负载。最小化负载有助于在 DDL 操作期间保持良好的性能和高吞吐量。

4、与表复制操作相比,在线操作将更少的数据读入缓冲池,从而减少了从内存中清除频繁访问的数据。清除频繁访问的数据可能会导致 DDL 操作后性能暂时下降。

LOCK 子句

默认情况下,MySQL 在 DDL 操作期间使用尽可能少的锁定。如果需要,可以为就地操作和一些复制操作指定LOCK子句以强制执行更严格的锁定。如果 LOCK子句指定的锁定级别低于特定 DDL 操作所允许的限制级别,则语句将失败并出现错误。 LOCK条件描述如下,按照从最少到最多限制的顺序:

1、LOCK=NONE:

允许并发查询和 DML。

例如,将此子句用于涉及客户注册或购买的表,以避免在冗长的 DDL 操作期间使表不可用。

2、LOCK=SHARED:

允许并发查询但阻止 DML。

例如,在数据仓库表上使用此子句,您可以将数据加载操作延迟到 DDL 操作完成,但不能长时间延迟查询。

3、LOCK=DEFAULT:

允许尽可能多的并发(并发查询、DML 或两者兼有)。省略LOCK子句与指定LOCK=DEFAULT一致。

当您不希望 DDL 语句的默认锁定级别导致表的任何可用性问题时,请使用此子句。

4、LOCK=EXCLUSIVE:

阻止并发查询和 DML。

如果主要关注的是在尽可能短的时间内完成 DDL 操作,并且不需要并发查询和 DML 访问,则使用此子句。如果服务器空闲,您也可以使用此子句,以避免意外的表访问。

在线 DDL 和元数据锁

在线 DDL 操作可以被视为具有三个阶段:

阶段 1:初始化

在初始化阶段,服务器根据存储引擎能力、语句中指定的操作以及用户指定的ALGORITHM选项来确定LOCK 操作期间允许的并发量。在此阶段,将采用共享的可升级元数据锁来保护当前表定义。

阶段 2:执行

在此阶段,准备并执行语句。元数据锁是否升级为独占取决于初始化阶段评估的因素。如果需要独占元数据锁,则仅在语句准备期间短暂使用。

阶段 3:提交表定义

在提交表定义阶段,元数据锁升级为独占,以逐出旧表定义并提交新表定义。一旦授予,独占元数据锁定的持续时间很短。

由于上面概述的独占元数据锁要求,在线 DDL 操作可能必须等待在表上持有元数据锁的并发事务提交或回滚。在 DDL 操作之前或期间启动的事务可以持有正在更改的表上的元数据锁。在长时间运行或非活动事务的情况下,在线 DDL 操作可能会超时等待独占元数据锁定。此外,在线 DDL 操作请求的未决独占元数据锁会阻塞表上的后续事务。

以下示例演示了等待独占元数据锁的在线 DDL 操作,以及挂起的元数据锁如何阻止表上的后续事务。

会话1:

mysql> CREATE TABLE t1 (c1 INT) ENGINE=InnoDB;mysql> START TRANSACTION;mysql> SELECT * FROM t1;

SELECT语句在表 t1 上获取共享元数据锁。

会话2:

mysql> ALTER TABLE t1 ADD COLUMN x INT, ALGORITHM=INPLACE, LOCK=NONE;

会话 2 中的在线 DDL 操作需要表 t1 上的独占元数据锁来提交表定义更改,必须等待会话 1 事务提交或回滚。

会话3:

mysql> SELECT * FROM t1;

会话 3 中发出的SELECT语句被阻塞,等待会话 2 中的ALTER TABLE 操作请求的独占元数据锁被授予。

您可以使用 SHOW FULL PROCESSLIST来确定事务是否正在等待元数据锁定。

mysql> SHOW FULL PROCESSLIST\G...*************************** 2. row ***************************Id: 5User: rootHost: localhostdb: testCommand: QueryTime: 44State: Waiting for table metadata lockInfo: ALTER TABLE t1 ADD COLUMN x INT, ALGORITHM=INPLACE, LOCK=NONE...*************************** 4. row ***************************Id: 7User: rootHost: localhostdb: testCommand: QueryTime: 5State: Waiting for table metadata lockInfo: SELECT * FROM t14 rows in set (0.00 sec)

元数据锁信息也通过 Performance Schema的metadata_locks 表公开,该表提供有关会话之间的元数据锁依赖关系、会话正在等待的元数据锁以及当前持有元数据锁的会话的信息。

在线 DDL 性能

DDL 操作的性能很大程度上取决于操作是否立即、就地执行以及是否重建表。

要评估 DDL 操作的相对性能,您可以使用ALGORITHM=INSTANT、 ALGORITHM=INPLACE和ALGORITHM=COPY比较结果。也可以在old_alter_table启用的情况下运行语句以强制使用ALGORITHM=COPY。

对于修改表数据的 DDL 操作,您可以通过查看命令完成后显示的“受影响的行”值 来确定 DDL 操作是执行就地更改还是执行表复制。例如:

1、更改列的默认值(快速,不影响表数据):

Query OK, 0 rows affected (0.07 sec)

2、添加索引(需要时间,但0 rows affected显示表没有被复制):

Query OK, 0 rows affected (21.42 sec)

3、更改列的数据类型(需要大量时间并且需要重建表的所有行):

Query OK, 1671168 rows affected (1 min 35.54 sec)

在对大表运行 DDL 操作之前,请检查操作是快还是慢,如下所示:

1、克隆表结构。

2、用少量数据填充克隆的表。

3、对克隆的表运行 DDL 操作。

4、检查“影响行”的值是否为零。非零值表示操作复制表数据,这可能需要特殊计划。例如,您可能会在计划的停机时间期间执行 DDL 操作,或者在每个副本服务器上一次执行一个。

因为记录并发 DML 操作所做的更改涉及一些处理工作,然后在最后应用这些更改,所以在线 DDL 操作总体上可能比阻止其他会话访问表的表复制机制花费更长的时间。原始性能的降低与使用该表的应用程序的更好响应性相平衡。在评估更改表结构的技术时,请根据网页加载时间等因素考虑最终用户对性能的看法。

标签: #mysql在线ddl不锁表 #mysql ddl 锁表 #ddlmysql