OMG_By

沉心、静气、学习、总结、进步


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

Docker 环境下搭建MySQL 8.0.20 组复制

发表于 2020-06-13 | 分类于 MySQL

最近在学习MySQL 8.0 新特性,以及MGR。于是想在搭建一套环境来测试。
本来在买的阿里云服务器上进行搭建,结果好像是一台机器搭建不了,至少需要三台,于是就放弃了。
正好小伙伴分享了docker,于是就利用docker在本地搭建了一套8.0的MGR环境。

准备docker镜像

运行一个test名称的centos系统镜像
➜ ~ docker run -d -it --name test centos
进入容器
➜ ~ docker exec -it test bash
在容器内安装MySQL

1
2
3
4
[root@c610b533f3dc /]# yum install yum-utils wget -y
[root@c610b533f3dc /]# wget https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
[root@c610b533f3dc /]# rpm -ivh mysql80-community-release-el7-1.noarch.rpm
[root@c610b533f3dc /]# yum install -y mysql-server

安装完后退出容器,并生成镜像

1
2
[root@c610b533f3dc /]# exit
➜ ~ docker commit 容器ID mysql8.0.20

启动MySQL容器

1
2
3
docker run -d -it --privileged --name=mysql-mgr-node1 mysql8.0.20 /usr/sbin/init
docker run -d -it --privileged --name=mysql-mgr-node2 mysql8.0.20 /usr/sbin/init
docker run -d -it --privileged --name=mysql-mgr-node3 mysql8.0.20 /usr/sbin/init
阅读全文 »

MySQL机制之Double Write

发表于 2020-06-07 | 分类于 MySQL

背景

我们知道MySQL在更新数据的时候,会先写入到内存中的数据页,然后再在一定的时机时,将脏页给刷新到磁盘中。
一个数据页默认为16k,但是由于操作系统的限制,每次需要多次才能将数据页给刷新到磁盘;如果在这个过程中发生故障,导致一个数据页并没有完整的给刷新到磁盘中。我们就称为页断裂 。在这种情况下,我们并不知道会出现什么未知的现象。
为了在页断裂场景发生时,能够对损坏的数据页进行修复工作。就引入了两次写(Double Write)机制。

什么是两次写

简单来说,就是在对数据页刷盘操作之前,先将该数据页写到一块独立的物理文件位置(ibdata)中。然后再将数据页进行刷盘操作。这样在宕机时,如果出现物理文件损坏,就能够利用ibdata中的副本文件进行修复行为。

Double Write由两部分组成;一部分是内存中的double write buffer,其大小为2M。另一部分由共享表空间(ibdata)中连续的128页,即2个区组成,大小也是2M。
其刷盘流程为:

  1. 当多个数据页需要进行刷盘时,并不直接写入到磁盘的物理文件中,而是先拷贝到内存中的double write buffer中。
  2. 接着从double write buffer中分两次写入到磁盘的共享表空间中(连续存储,顺序写,性能很高),每次写1M。
  3. 等第二步完成后,再将double write buffer中的脏页数据写入到实际的各个表空间中(离散写)

阅读全文 »

pt-osc死锁分析记录两则

发表于 2020-06-04 | 分类于 MySQL

背景

今天看到叶老师公众号推送文章《pt-osc在线重建表导致死锁的分析及对应的优化方案》,让我想起了前段时间同样遇到了pt-osc改表导致的死锁。故此记录一下。

pt-osc

pt-online-schema-change:PERCONA提供的在线改表工具,避免MySQL在执行改表操作时造成的锁表和主从延迟情况发生。

工作原理

1、创建一个跟原表表结构一样的新表。取名为_oldTableNmae_new
2、修改新表结构
3、在原表中创建insert、update、delete三个类型的触发器,用于做增量数据迁移。原表SQL和触发器触发SQL在同一事务当中。
4、以一定块大小(chunk-size)从原表拷贝数据到新表
5、数据拷贝完后,修改表名:rename table to table_old; rename _table_new to table
6、删除old表,删除三个触发器

版本变化

3.0.2之前的update触发器:

1
REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`, `c1`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`, NEW.`c1`)

3.0.2之后的update触发器:

1
2
3
4
BEGIN
DELETE IGNORE FROM `lc`.`_hb_new` WHERE !(OLD.`id` <=> NEW.`id`) AND `lc`.`_hb_new`.`id` <=> OLD.`id`;
REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`);
END

阅读全文 »

MySQL机制之index merge

发表于 2020-05-31 | 分类于 MySQL

背景

查询时where后面可能会涉及到多个字段,它们之间进行AND或OR。在MySQL 5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。从5.1开始引入了index merge技术。
index merge技术就是对多个索引分别进行条件扫描,然后将他们各自的结果进行合并

该特性主要会体现在以下场景:

  1. 对OR语句求并集
  2. 对AND语句求交集
  3. 对AND和OR组合语句求结果

在满足index merge条件下的查询计划中会出现type:index_merge。

AND取交集(union)

union就是多个索引条件扫描,对得到的结果进行并集运算,显然是多个条件之间进行的是 OR 运算。
案例:SELECT * FROM tmp_index_merge where key1_part1 = 2 and key2_part1 = 4\G

OR取并集(intersect)

intersect就是多个索引条件扫描得到的结果进行交集运算。
案例:SELECT * FROM tmp_index_merge where key1_part1 = 2 or key2_part1 = 4\G

AND和OR组合取并集(sort_union)

多个条件扫描进行 OR 运算,但是不符合 index union merge算法的,此时可能会使用 sort_union算法。

1
2
SELECT * FROM tbl_name WHERE key_col1 < 10 OR key_col2 < 20;
SELECT * FROM tbl_name WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col=30;

注意

在MySQL5.6.7之前的版本中,存在range优先原则。只要可以使用Range访问方式,那就不会再使用index merge。

总结

索引合并机制并不是什么新鲜东西,但是仍然存在很多人认为一条查询只能使用一个索引的观念。本篇文章只是简单的介绍MySQL存在这么一个机制,并未过深的研究。
简言之,索引合并会同时利用多个索引进行查询,尽可能得过滤掉不需要的数据行,然后再进行一次统一的回表行为。较少无谓的回表行为。

http://dev.mysql.com/doc/refman/5.6/en/index-merge-optimization.html
https://www.orczhou.com/index.php/2013/01/mysql-source-code-query-optimization-index-merge/
http://www.cnblogs.com/nocode/archive/2013/01/28/2880654.html

MySQL机制介绍之NLJ、BNL、BKA

发表于 2020-05-30 | 分类于 MySQL

背景

MySQL 5.5版本前,MySQL本身只支持一种表间关联方式,就是嵌套循环(Nested Loop)。如果关联表的数据量很大,则join关联的执行时间会非常长。
在5.5版本中,MySQL通过引入Block Nested-Loop Join(BNL)算法来优化嵌套执行。

NLJ

将驱动表的结果集作为循环基础数据,然后循环从该结果集中每次一条获取数据作为下一个表的过滤条件查询数据,然后合并结果。
如果有多表join,则将前面的表的结果集作为循环数据,取到每行再到链接的下一个表循环匹配。

SNLJ

Simple Nested-Loops Join(SNLJ,简单嵌套循环联接),该算法比较简单、直接。驱动表中的每一条记录都与被驱动表中的记录进行匹配判断。对于两表连接,驱动表只需要被访问一次,而被驱动表需要访问多次。这个算法的开销非常大,复杂度为笛卡尔积。

其实现伪代码如下:

1
2
3
4
For each row r in R do                         -- 扫描R表(驱动表)
For each row s in S do -- 扫描S表(被驱动表)
If r and s satisfy the join condition -- 如果r和s满足join条件
Then output the tuple <r, s> -- 返回结果集

阅读全文 »

MySQL机制介绍之ICP

发表于 2020-05-28 | 分类于 MySQL

ICP是什么

Index Condition Pushdown,也称为索引条件下推,体现在执行计划中会出现Using index condition。
ICP优化适用于MySQL利用索引从表里检索数据的场景。
使用命令set optimizer_switch='index_condition_pushdown=on'开启

使用场景

  • 索引访问方式是range/ref/eq_ref/ref_or_null,并且需要访问表的完整行记录
  • InnoDB和MYISAM表,包括分区的表(5.7)
  • 对于InnoDB表,ICP只适用于二级索引。ICP的目标是减少访问表的完整行的读取量从而减少IO操作。
  • 不支持建立在虚拟列上的二级索引
  • 引用子查询、存储函数的条件没法下推
  • Triggered conditions 也没法下推

原理

不使用ICP

  1. 用二级索引查找数据的主键
  2. 用主键回表读取完整的行记录
  3. 引擎层利用where语句的条件对行记录进行过滤

使用ICP

  1. 用二级索引查找数据的主键
  2. 如果where条件中的字段在复合索引中,引擎层对where条件里的字段进行过滤后,返回主键
  3. 利用主键回表读取完整的行记录
  4. 引擎层用where语句的剩余条件对行记录进行过滤

结论

ICP的优化在引擎层就能够过滤掉大量的数据,这样无疑能够减少了对base table和mysql server的访问次数,提升了性能。

https://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html
https://yq.aliyun.com/articles/259696
https://zhuanlan.zhihu.com/p/73035620

MySQL机制介绍之MRR

发表于 2020-05-27 | 分类于 MySQL

什么是MRR

Multi-Range Read Optimization,是优化器将随机IO转换成顺序IO以降低查询过程中IO开销的一种手段。
它的好处有:

  • 使数据访问由随机变为顺序
  • 减少缓冲池中页被替换的次数
  • 批量处理查询操作

可以通过set optimizer_switch='mrr=on';命令进行开启。

不使用MRR

1
2
3
4
5
6
7
8
9
10
mysql> set optimizer_switch='mrr=off';
Query OK, 0 rows affected (0.00 sec)

mysql> explain select * from test.t1 where (a between 1 and 10) and (c between 9 and 10) ;
+----+-------------+-------+-------+---------------+------+---------+------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+------+------------------------------------+
| 1 | SIMPLE | t1 | range | mrrx,xx | xx | 5 | NULL | 2 | Using index condition; Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+------------------------------------+
1 row in set (0.00 sec)

在不使用MRR时,优化器需要根据二级索引返回的记录来进行回表,这个过程一般会有较多的随机IO操作。

使用MRR

1
2
3
4
5
6
7
8
9
10
mysql> set optimizer_switch='mrr=on';
Query OK, 0 rows affected (0.00 sec)

mysql> explain select * from test.t1 where (a between 1 and 10) and (c between 9 and 10) ;
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------------------------------+
| 1 | SIMPLE | t1 | range | mrrx,xx | xx | 5 | NULL | 2 | Using index condition; Using where; Using MRR |
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------------------------------+
1 row in set (0.00 sec)

在使用了MRR时,SQL语句的执行过程为:

  1. 优化器将二级索引查询到的记录放到一块缓冲区中(read_rnd_buffer_size)
  2. 如果二级索引扫描到文件末尾或者缓冲区已满,则使用快排对缓冲区中的内容按照主键进行排序
  3. 用户线程调用MRR接口获取cluster index,然后根据cluster index获取行数据
  4. 当缓冲区中的cluster index取完数据,则继续调用过程2、3,直到扫描结束

总结

MRR特性就是在查询过程中,先将满足条件的id查询出来并进行排序后,再进行批量查询操作。从而实现随机IO到顺序IO的转换,提升性能。

https://dev.mysql.com/doc/refman/5.6/en/mrr-optimization.html
https://zhuanlan.zhihu.com/p/110154066

Redis扩展命令实现

发表于 2020-05-17 | 分类于 Redis

上周,参加公司后端部门开发的分享。
在期间,该开发吐槽Redis好几个使用不便利的地方。

  1. Redis没有批量设置过期时间的命令
  2. incr 不存在的key的时候,并不会设置过期时间。导致持久化key的存在

阅读全文 »

MySQL闪回工具调研

发表于 2020-05-17 | 分类于 MySQL

刚入职2个月左右的时候,就遇到了业务误操作,将对测试环境的delete操作,到线上执行了。。。(至于业务为什么有delete权限的账号,俺也不知道)
由于公司所有实例都部署在阿里云上,所以只能依赖于阿里云的备份恢复系统来进行数据恢复。但是非常慢,当时是大概花了20分钟才完全恢复(-_-||)。
于是乎~工作量又被增加了。领导让我调研数据闪回工具。。。

在工具调研测试过程中,发现了这几个工具存在部分BUG问题,所以给记录一下。避免再次踩坑。

MyFlash

MyFlash是由美团点评公司技术工程部开发维护的一个回滚DML操作的工具。该工具通过解析v4版本的binlog,完成回滚操作。相对已有的回滚工具,其增加了更多的过滤选项,让回滚更加容易。

通过解析binlog来生成回滚binlog文件。

优缺点

优点:

  • 多种过滤条件,能够按照需求实现精准过滤
  • 支持离线解析。不会对运行实例造成影响

缺点:

  • binlog格式必须为row,并且binlog_row_image=full。
  • 只支持5.6和5.7
  • 只支持DML,不支持DDL
  • MyFlash不能解析阿里云RDS的binlog
阅读全文 »

Redis哨兵client-reconfig-script脚本bug记录一则

发表于 2020-05-17 | 分类于 Redis

前一阵子一直在做自建机房Redis主从的环境搭建。了解到哨兵高可用切换后的会调用client-reconfig-script参数配置的脚本。
但是遇到了一个从2.8版本一直存在至今的BUG。我已经提了一个PR给官方,并被meger了。https://github.com/antirez/redis/pull/7113
特此记录一下。

BUG场景

手动将主实例kill掉,模拟宕机情况。在某些情况下,哨兵已经触发了高可用切换行为(主从状态、日志均有)。但是并没有调用配置的脚本(非必现,但是落到同一台机器调用时并不会调用)
重启该机器上的哨兵节点又恢复正常。(重启大法好)

阅读全文 »
123…14
OMG_By

OMG_By

133 日志
20 分类
36 标签
RSS
GitHub E-Mail
友链
  • 戎码人生
  • JosemyQAQ
  • Just do it !
  • ACM各大OJ题集
  • django大神博客
© 2020 OMG_By