MySQL内核月报 2014.12-MySQL· 性能优化·并行复制外建约束问题

背景:

mysql 主备同步是通过binlog来进行的,备库的 IO 线程从主库拉取binlog,SQL线程将拉取的binlog应用到备库,在5.6之前,备库只有一个线程应用binlog,主库的更新量大,且备库的执行效率低时,就会造成了大量从主库拉取的binlog来不及执行,因此造成了主备延迟问题。为了解决主备延迟,需要提高备库的执行效率,阿里MySQL 设计并开发了并行复制功能,所谓并行复制,指的是应用binlog的线程数量是多个的,而不是原生的单个线程,经过测试可以极大的提高复制性能(有3X的性能提升),在并行复制中,一个 IO 线程,一个分发线程,多个sql_thread,分发线程读取relay log,并将读取的relay log 分发给多个sql_thread, 从而实现并行化的效果。

原理:

分发线程的分发原理是依据当前事务所操作的表的名称来进行分发的,如果事务是跨表的(一个事务更新多张表),则需要等待已分配的该表相关的事务全部执行完毕,才会继续分发,其分配行为的伪码可以简单的描述如下:


问题描述(testcase):

drop table t2 if exists t2;
drop table t1 if exists t1;
create table t1(c1 int primary key, c2 int);
create table t2(c1 int primary key, c2 int , foreign key (c2) references t1(c1));
insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t2 values(1,1);
insert into t2 values(2,2);

以下两个语句在备库的执行顺序不同,结果会不同

delete from t2 where c2=1; (语句1)

update t1 set c1=3 where c1=1;(语句2)

如果语句2先于语句1在备库执行,则会报外建约束错误,因为在上述的分发原理中没有考虑到外建约束问题,这种情况下,只有串行化处理了,当然,你可以执行:set global foreign_key_checks=off;然后start slave;在类似语句执行完后,再恢复foreign check,但是这样做真正安全吗?答案是不一定的……

情况1:

create table t1(c1 int primary key, c2 int);

create table t2(c1 int primary key, c2 int , foreign key (c2) references t1(c1));

在这种定义下,如果不检测foreign key,则不会有问题,因为对t1, t2的操作都会记录binlog;

情况2:

create table t1(c1 int primary key, c2 int);

create table t2(c1 int primary key, c2 int , foreign key (c2) references t1(c1) on delete cascade);

在这种定义下,如果不检测foreign key,则会有问题,因为对表t1的操作会影响t2表,在检测foreign key的时候,会进行相应的cascade操作,如果不检测foreign key,则不进行级联操作,这种问题一旦发生,则会引起主备不一致问题。

解决方法

5.6 并行复制没有此问题,5.6中在检测到foreign key的事件时,会等待已经分发的所有binlog都已执行完再执行,因此解决了此问题。

改进方案 这个方案虽然能解决问题,但是若系统中只要出现一个外键关系,并且持续有更新,会导致持续性的回退到单线程方案,那么多线程复制的效果就会大打折扣。实际上这个做法比较极端,改进的方案是,遇到有foreign key 的表,应该将其分发到依赖他的表的同一个sql thread 中。这样执行这些事务时,其他表的并行复制仍能继续。

时间: 2024-12-28 18:27:57

MySQL内核月报 2014.12-MySQL· 性能优化·并行复制外建约束问题的相关文章

MySQL内核月报 2014.12-MySQL· 性能优化·5.7 Innodb事务系统

背景知识 为了便于理解下文,我们先简单梳理下Innodb中的事务.视图.多版本的相关背景知识. 在Innodb中,每次开启一个事务时,都会为该session分配一个事务对象.而为了对全局所有的事务进行控制和协调,有一个全局对象trx_sys,对trx_sys相关成员的操作需要trx_sys->mutex锁. Innodb使用一种称做ReadView(视图)的对象来判断事务的可见性(也就是ACID中的隔离性).根据可见性原则,某个新开启的事务不应该看到其他未提交的事务. Innodb在执行一个SE

MySQL内核月报 2014.12-MySQL· 性能优化·thread pool 原理分析

大连接问题 现有mysql 处理客户端连接的方式会触发mysql 新建一个线程来处理新的连接,新建的线程会处理该连接所发送的所有 SQL 请求,即 one-thread-per-connection 的方式,其创建连接的堆栈为: 线程建立后,处理请求的堆栈如下: 0 mysql_execute_command 1 0x0000000000936f40 in mysql_parse 2 0x0000000000920664 in dispatch_command 3 0x000000000091e

MySQL内核月报 2014.12-MySQL· 性能优化·Bulk Load for CREATE INDEX

背景 MySQL5.6以后的版本提供了多种优化手段用于create index,比如online方式,Bulk Load方式. Online提供了非阻塞写入的方式创建索引,为运维提供了很大的便利. Bulk Load提升了索引创建的效率,减少了阻塞的时间. 这篇介绍下MySQL 5.7.5 Bulk Load的细节,并从查找,排序,redo,undo,page split等维度比较一下传统方式和Bulk Load方式. 传统方式 MySQL 5.7.5版本之前,create index使用的是和

MySQL内核月报 2014.11-MariaDB· 性能优化·filesort with small LIMIT optimization

从MySQL 5.6.2/MariaDB 10.0.0版本开始,MySQL/MariaDB针对"ORDER BY ...LIMIT n"语句实现了一种新的优化策略.当n足够小的时候,优化器会采用一个容积为n的优先队列来进行排序,而不是排序所有数据然后取出前n条. 这个新算法可以这么描述:(假设是ASC排序) 建立一个只有n个元素的优先队列(堆),根节点为堆中最大元素 根据其他条件,依次从表中取出一行数据 如果当前行的排序关键字小于堆头,则把当前元素替换堆头,重新Shift保持堆的特性

MySQL内核月报 2014.11-TokuDB· 版本优化· 7.5.0

TokuDB 7.5.0大版本已发布,是一个里程碑的版本,这里谈几点优化,以飨存储引擎爱好者们. a) shutdown加速 有用户反馈TokuDB在shutdown的时候,半个小时还没完事,非常不可接受. 在shutdown的时候,TokuDB在干什么呢?在做checkpoint,把内存中的节点数据序列化并压缩到磁盘. 那为什么如此耗时呢?如果tokudb_cache_size开的比较大,内存中的节点会非常多,在shutdown的时候,大家都排队等着被压缩到磁盘(串行的). 在7.5.0版本,

MySQL · 捉虫动态 · 并行复制外键约束问题二

背景 并行复制可以大大提高备库的 binlog 应用速度,内核月报也多次对并行复制特性进行介绍,感兴趣的朋友可以回顾下:5.6 并行复制实现分析.5.6 并行复制恢复实现 和 5.6并行复制事件分发机制. 在早期的内核月报,有一篇 并行复制外建约束问题,介绍阿里在 5.5 版本中自己实现并行复制时遇到的外键约束问题,本文接着前作继续介绍并行复制外键约束问题,这次场景不一样,并且目前官方 5.6 最新版本(5.6.30)中也有这个问题. 问题描述 一般情况的复制是 A->B 这样一主一备,本文要描

MySQL内核月报 2014.12-MySQL· 优化改进· GTID启动优化

背景 GTID 可以说是 MySQL 5.6 版本的一个杀手级特性,它给主备复制带来了极大的便利,RDS只读实例就是强依赖于这个特性.然而GTID在给我们带来便利的同时,也埋下了许多坑,最近几期内核月报中GTID的频繁出现也说明了这一点,对其我们可以说是既爱又恨. GTID 并不是免费午餐,要使用它是要有代价的,为了保证GTID这个体系能够运转起来,需要做许多相关的工作,比如binlog里每个事务要多记 gtid_event 这种事件.写binlog的时候要生成 gtid.要维护几个GTID集合

MySQL内核月报 2014.11-MySQL· 5.7优化·Metadata Lock子系统的优化

背景 引入MDL锁的目的,最初是为了解决著名的bug#989,在MySQL 5.1及之前的版本,事务执行过程中并不维护涉及到的所有表的Metatdata 锁,极易出现复制中断,例如如下执行序列: Session 1: BEGIN; Session 1: INSERT INTO t1 VALUES (1); Session 2: Drop table t1; --------SQL写入BINLOG Session 1: COMMIT; -----事务写入BINLOG 在备库重放 binlog时,会

MySQL内核月报 2014.09-MariaDB· 性能优化·Extended Keys

MariaDB 10.0.8增加了一种新的执行计划--Extended Keys. 它充分利用了InnoDB的隐藏列来做执行计划,因为我们都知道InnoDB的索引组织表会把主键放在最末尾,所以实际上每个索引最后都包含了主键. 打开和关闭这个优化器选项的命令如下: Enable: Disable: MariaDB 10.0.8中默认选项是 'extended_keys=off'. MariaDB 10.0.9开始默认选项是 'extended_keys=on'. 看一个例子: 有一个DBT-3/T