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

Pthread mutex与GCC atomic性能测试

问题背景

之前对这一块只有一个初步的理解,阅读过一些文章,大概知道pthread中mutex一次加锁时间在10~100ns之间,直觉上认为这个效率非常高了,最近做MySQL高并发优化工作后,发现自己知道的太少,以致浪费了不少时间,遂决定通过测试总结一下最近学习到的东西

mutex的主要作用是保证原子性操作,pthread实现提供的一套api非常简洁,对于一般的应用肯定是够了,但是对于Database这种对性能有变态要求的系统,尤其是在高并发下,需要进一步优化,这时需要用到gcc提供的__sync_xxx_and_fetch系列函数了,具体参考:GCC Atomic Memory Access and built-in functions,这系列函数使用内存屏障保证对内存单元的原子操作,性能较pthread好,本文通过一系列测试得出定量结论
[……]

Read more

InnoDB 读写锁rw_lock_t实现

10月忙得像shi一样,不管怎样,忙里偷闲在这个月结束之前写上一篇,介绍InnoDB读写锁的实现

InnoDB读写锁特点

1. 读与读之间不冲突,读与写,写与写之间冲突,这个是读写锁最基本的特征
2. 申请写锁时,如果锁被读持有,将发生写锁等待,该写锁之后的所有读锁会等待该写锁成功获取后才能申请成功,这保证了公平:写锁请求不会被饿死

基本数据结构

sync_array_struct: 保存用于线程同步结构的数组,数组成员类型为sync_cell_struct
sync_cell_struct: 一个线程同步结构体,部分代码:[……]

Read more

MySQL threads running control

问题背景

线上MySQL经常遇到threads_running飙高的情况,往往在这种情况下,MySQL server会表现出hang住的假象,其实threads_running是一种结果,表示问题已经发生了,如果此时不找出问题原因采取措施,会影响到线上应用,为此我们开发了MySQL threads running control特性,监测threads_running,当发现其超过一个阈值时,server暂时拒绝服务,避免引起雪崩,待threads_running下降后正常服务。

什么是threads_running

threads_running是MySQL一个重要的实时运行状态参数,通过

SHOW STATUS LIKE ‘threads_running’;

可以查到,它代表的意义:当前并发执行的statement/command的数目,每个statement/command开始执行之前将其增加1,执行结束后减1,代码中的逻辑:[……]

Read more

Category: 未分类

InnoDB 锁系统及死锁检测实现分析

死锁检测一般采用Wait-For-Graph算法,这个不是非常复杂或者新奇的内容,cs课程中一般都会交代,本文从代码层面解析InnoDB锁系统及死锁检测实现,一方面给自己阅读代码做做笔记,另一方面希望也能够为一些有疑惑的朋友提供帮助

几个问题

1. InnoDB中锁在是怎样表示和维护的
2. 死锁检测发生在什么时候
3. InnoDB中的Wait-For-Graph是如何实现的
4. InnoDB通常在哪些情况下可能发生死锁
[……]

Read more

MySQL embedded server prepared statement执行分析

MySQL embedded server简介

MySQL可以作为一个embedded server执行,这时它就充当了一个与应用紧密耦合的轻量级数据中心,适合资源有限、应用需要连接很少(通常1个)的场景,使用方便,编译后就可以随应用一起启动,具有部署方便,速度更快的优点,当然它有很多限制,如:不支持UDF,不支持主备复制,InnoDB层不支持多个连接等,更多请参考 libmysqld, the Embedded MySQL Server Library.

因为DRC团队在使用embedded server的过程中遇到了执行prepared statment时内存泄露的问题,为了定位并fix问题,分析了这部分逻辑
[……]

Read more