Galera replication for MySQL

这篇文章总结了之前对Galera replication的调研,内容包括Galera特性,原理,Galera cluster配置,参数及性能等

Galera replication是什么

MySQL DBA及开发应该都知道MySQL源生复制及semi-sync半同步复制,它们都基于MySQL binlog,原生复制是完全异步的,master不需要保证slave接收并执行了binlog,能够保证master最大性能,但是slave可能存在延迟,主备数据无法保证一致性,在不停服务的前提下如果master宕机让slave顶上,就会丢失数据,semi-sync在异步复制基础上增加了数据保护的考虑,master必须确认slave收到binlog后(但不保证slave执行了事务)才能最终提交事务,在没有退化(延迟较大时可能发生)成异步复制之前可以保证数据安全,此时master挂掉之后,slave可以在apply完所有relay log后切换成master提供读写服务

Galera replication是codership提供的MySQL数据同步方案,具有高可用,易于扩展等特点,它将多个MySQL节点组织成一个cluster
[......]

Read more

MySQL metadata lock源码分析

花了些时间理了下MySQL Meatadata Lock(元数据锁,有人将其翻译为数据字典锁)的实现,文章内容比较偏源码层面,在如何使用方面有些欠缺,需要对数据库系统原理或者MySQL实现有一定基础才不会觉得枯燥,如果连S/X/IS/IX及他们之间的关系都不清楚,建议先学习这部分知识!

源码版本:
Oracle MySQL community server 5.6.16

关键数据结构:

MDL_map
管理系统中所有的mdl(MDL_lock),为了减小锁竞争,被划分为mdl_locks_hash_partitions(默认为8)部分,该类全局只有一个对象:mdl_locks

MDL_map_partition
MDL_map中的一个partition,使用hash存储部分mdl(MDL_lock)
[......]

Read more

MyISAM表一例查询性能问题排查

问题背景

线上相同结构的两个MyISAM表,数据量差不多,执行的SQL查询计划基本一致,但是执行时间却相差很大

mysql> select * from auction_info_d__201402 where unit_id=7016 and day='2014-03-27';
Empty set (0.31 sec)
mysql> select * from auction_info_d__201403 where unit_id=7016 and day='2013-03-27';
Empty set (19.81 sec)

MySQL版本:

mysql> select @@version;
+------------+
| @@version  |
+------------+
| 5.1.48-log |
+------------+
1 row in set (0.00 sec)

[......]

Read more

SELECT…FROM UPDATE 特性介绍及性能测试

使用背景:

将update+select两条SQL合并成单条SQL,向客户端直接返回update之后的结果列,通过减小网络开销及sql解析代价提高性能

特性描述:

postgresql的语法是returning … as …

http://www.postgresql.org/docs/9.1/static/sql-update.html

oracle的语法是returning…into…

http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/returninginto_clause.htm#LNPLS01354

MySQL中由于需要兼容MySQL JDBC,我们将这个特性实现为:SELECT…FROM UPDATE…

[......]

Read more

MySQL threadpool(优先队列)介绍及性能测试

背景介绍

MySQL常用(目前线上使用)的线程调度方式是one-thread-per-connection(每连接一个线程),server为每一个连接创建一个线程来服务,连接断开后,这个线程进入thread_cache或者直接退出(取决于thread_cache设置及系统当前已经cache的线程数目),one-thread-per-connection调度的好处是实现简单,而且能够在系统没有遇到瓶颈之前保证较小的响应时间,比较适合活跃的长连接的应用场景,而在大量短连接或者高并发情况下,one-thread-per-connection需要创建/调度大量的线程,产生较高的的context-switch代价,从而使得系统性能下降
[......]

Read more

MySQL semi-sync 实现原理分析

本文分析基于Oracle MySQL 5.6.15版本源码,是在阅读MySQL源码以及印风博客基础上总结的,作为新年的第一篇博文,总结去年底的一点学习所得,将重点总结以下内容:
1). binlog group commit
2). semi-sync replication

binlog group commit

这是一个很古老的问题,简单啰嗦一下:为了保证数据安全,事务提交时需要将binlog刷盘,这个其实是分为2歩来做的,write和fsync,其中第二步保证数据持久化,非常耗时,会成为性能瓶颈,如果每提交一个事务都做一次fsync,系统TPS将会大大降低,为了解决这个问题,需要减少fsyn调用的次数,原理:活跃系统中,在一个线程做fsync时,其它线程将等待,等待过程中从这些线程中选出一个leader(进入等待的第一个线程),其它线程由leader代为完成write+fync,leader完成工作后通知所有等待的线程继续运行
[......]

Read more

MySQL自我保护与并发优化

问题背景

线上MySQL在大促时遇到并发压力大导致threads_running(并发执行query的线程数目)飙升,MySQL出现性能抖动问题甚至hang住,虽然在InnoDB层有innodb_thread_concurrency限制同时进入InnoDB存储层读写数据的线程数,但是这个参数不是一个硬限制(线程在锁等待结束后强制进入InnoDB层),而且代码路径比较靠后,作用有限,于尝试在server层限制并发数来解决这个问题,通过不断地优化和测试,开发完成了一个高水位限流/低水位优化的patch

patch功能介绍

这个patch是在之前thread running control的基础上优化的,将之前位于同一个函数中两个功能独立出来并将之前低水位限流实现从基于sleep-retry的机制优化成基于FIFO的cond-wait/signal机制
[......]

Read more

InnoDB并发控制模型

赶在2014之前,写下2013最后一篇技术博客,介绍一下InnDB的并发控制模型

背景知识

InnoDB中为什么需要并发控制?要回答这个问题,需要先聊聊context switch,当同时执行的进程/线程超过cpu核心数(超线程的数目)时,cpu以时间片轮转调度执行多个进程的时候就有context switch了,当进程A的时间片用完需要调度另外进程B时,需要将进程A的状态和参数保存在堆栈中,等再次调度到A时,再从堆栈中恢复状态和参数,这个切换的代价就是context switch,context switch的代价根据CPU性能及进程空间大小的不同,开销从几微秒(us)到几毫秒(ms)级别(参考:Quantifying The Cost of Context Switchhow-long-does-it-take-to-make-context),相对于一次内存读写操作(100ns左右),context switch代价不可小视(按照100us计算的话,相当于1000次内存访问)
[......]

Read more

InnoDB使用linux native aio源码分析

好记性不如烂笔头,这篇文章是一个学习和总结,包括linux native aio API介绍以及InnoDB中如何使用native aio

异步io

linux上异步io有两套API,posix aio和native aio,其中native aio具有更好的性能,但要求文件打开方式必须是O_DIRECT,简单列下两套API的接口:
[table caption="posix aio" width="500" colwidth="80|420" colalign="left|left" border="1"]
function,desc
aio_read,发起一个异步读请求
aio_write,发起一个异步写请求
aio_return,阻塞等待异步io请求返回
aio_error,检查异步io返回结果
aio_suspend,挂起调用进程,直到一个或多个异步请求已经完成(或失败)
aio_cancel,取消异步io
lio_listio,发起一系列异步io请求
[/table][......]

Read more

使用DEBUG_SYNC排查MySQL truncate问题

线上问题

DBA用脚本发送truncate操作清理MySQL表中数据,脚本执行一段时间使用ctrl+c想取消操作,却导致slave同步binlog后数据不一致,复制中断,之后通过select发现master表中数据依旧存在,但是truncate对应的binlog被记录记录,而slave中的表数据被清理,因为binlog复制过来后truncate操作执行成功

重现问题

这个问题比较诡异,truncate实际上是失败,但是binlog记录下来,我们知道binlog记录一个完整事务,只有当事务成功执行完才会写binlog,只有问题能够重现才可能找到原因,遂测试truncate发送后马上ctrl+c取消,然而每次truncate都成功,表中数据被清理,binlog也记录下来,后来思考DBA当时使用的是脚本,发送的是多条truncat操作,这样的话可以让truncate执行过程中被打断的位置尽可能的多,这样复现问题的可能性也高一些,经过多轮尝试,终于重现了:[......]

Read more