MySQL

  • 偶尔我们需要这样做。

    在一台主机上如果复制多个主库,可以很简单:在备库主机上启动多个MySQL实例(mysqld_muilt),每个实例使用一个端口,复制多台主库就可以了。但是如果希望复制过来的数据都在同一个实例中,事情就复杂了。

    1. 问题以及开源社区的尝试

    需求:多个主库都复制到一个备库,复制过来的数据都在一个实例中,这样实现对应用层的透明。目前,MySQL本身不提供这样的功能(考虑过,但一直未实现)。

    1.1 开源社区也有很多方案和想法,例如Tungsten replicator:可以支持异构数据复制,JAVA实现,数据量较大时,性能较差,而且MySQL版本更新较快,而该软件支持较慢;

    1.2 再如P.Linux的尝试:通过拉取多个主库上的Binlog在单个备库上应用的方式,对MySQL没有入侵,实现也较为简单。

    1.3 High Performance MySQL还可以通过多级复制的方式实现:例如有主库DB1、DB2,都需要复制到S1上,则先配置D2复制D1的全部数据,然后再从S1上复制D2的全部数据就可以了。整理需要注意D2上的log-slave-update需要打开,为了减少D2的压力,DB上复制过来的表可以全部使用Blackhole引擎

    1.4 另外,还有一些欠成熟的Patch实现。

    2. MySQL Federated引擎的“软链接”特性

    Federated引擎可以在本地数据库中创建一个远端数据表的“软链接”。这样,访问远端数据表就如同访问本地数据表。(这里远端可以是不同主机上的不同实例)

    se-federated-structure

    3. 使用Federated数据表实现多主一备

    例如,主库DB1,DB2,都需要复制到S1上,这里DB1,DB2,S1分别在主机H1,H2,H3上。首先,在主机H3(S1所在的主机)上其另外起两个MySQL实例S2、S3,分别复制主库DB1和DB2,然后在实例S1上建立多个Federated表关联S2、S3中的数据表(相当于在S1中建立到S2、S3的软连接)。

    Federated-Muilt-master

    这时应用,连接到S1,就可以同时透明的访问到DB1、DB2中的实时数据表了。

    4. 一些说明

    4.1 上面描述的方法,也可以直接在S1上建立到DB1、DB2各个表的软连接,但是为了最大程度的减少对主库的影响,最好如上多配一层备库。

    4.2 最简单的可以直接在备库上配置多个实例,让应用连接多个实例就好了,无需上面这么复制的配置。

    参考文献:

    1. MySQL Manual: The FEDERATED Storage Engine

    2. Post of MySQL Forums : Multiple masters to single slave

    3. 通过tungsten replicator实现mysql多主一从的备份架构

    4. Is it possible to do N-master => 1-slave replication with MySQL

    5. MySQL Multi-Master – Single-Slave – Replication

  • 格式化输出SQL

    ·

    工作中,经常需要在web页面中把SQL(MySQL)展示给开发人员,如果SQL不格式话,例如:

    sqlsample_1

    上面的SQL,咋一眼,很难看出SQL的目的是什么。而格式化的输出可以让SQL更易读懂,如:

    screenshot-sqlparser

    上周末做了一个简单的PHP SQL Format工具,可以实现上述功能,这里简单的介绍如何使用PHP SQL Format(也可以参考这里)。

    1. 下载相关文件并解压到你的WEB目录

    有如下文件:

    将这些文件都放入web目录下的sqlparserlib目录下。

    2. 编写如下PHP/HTML代码
    <link rel="stylesheet" type="text/css" href="sqlparserlib/sqlsyntax.css" /> <?php define('PARSER_LIB_ROOT', "/opt/www/sqlparserlib/"); require_once PARSER_LIB_ROOT.'sqlparser.lib.php'; function SQLFormatPHP($sql){ return PMA_SQP_formatHtml(PMA_SQP_parse($sql)); } $sql = "SELECT FROM (select from dual)"; echo SQLFormatPHP($sql); ?>

    只要把上面php代码中的$sql改成你的输入SQL就OK了。

    3. 需要注意的问题

    * 上面的代码中,路径一定要注意,在你的代码中也必须引用正确的路径

    * 上面的sqlsyntax.css定义了很多CSS,注意不要与你的CSS冲突了

    * 上面require_once很多函数,注意不要与你的函数冲突了

    4. 实现说明

    这里使用的代码包sqlparser.lib.php来自phpMyAdmin,稍微做了一些改动,让这块代码能够独立使用。

    看了Stackoverflow上很多朋友也有类似问题,所以就花了几个小时的尝试,把phpMyAdmin里面SQL Parser相关的代码独立出来,lib中有很多的代码都应该是无用的,我并没有做精简,所以你最求效率的话,可能需要自己再优化一下。

  • idata-Forum分享

    ·

    刚刚完成在idata-forum的主题分享,介绍了一下最近一年在MySQL方面的尝试,包括性能调优,代码优化方面的内容。

    不再紧张了。

  • 也说快速关闭MySQL/InnoDB

    ·

    如果用的引擎是InnoDB,每次敲下mysqladmin -uroot -p shutdown关闭数据库的时候,总是很难预测这个命令会执行多久,实际经验表明,短则五秒,长则三十分钟一小时都有可能。也分享一下我的经验吧。

    1. 为什么InnoDB关闭会慢?

    事实上,并不是每次关闭InnoDB都很慢的。Why?InnoDB较之MyISAM,一个重要特性是InnoDB会在内存中开辟一个Buffer Pool来存储最近访问的数据块/索引块,使得下次再次访问这个块时速度能够很快。当InnoDB对需要修改数据块的时候,会先记录修改日志,然后直接对Buffer_Pool中的数据块的操作。记录日志是顺序写,对数据块的操作是内存操作,这让InnoDB在很多场景下有这很好的速度优势。 (more…)

  • Flashcache配置

    ·

    前面写了两篇文章,分别介绍了Flashcache的基本原理和编译安装,本文介绍一下Flashcache的配置。

    假设现在你已经编译好了Flashcache,已经装好了ssd盘(假设是/dev/sdb)和sas盘(假设需要使用的是分区/dev/sda12,这可能是一个RAID组)。接下来,看看如何使用Flashcache将上面两个设备虚拟成一个带缓存的块设备。

    1. 首次创建Flashcach设备

    注:请备份你的数据先!!!特别是/dev/sdb,这个设备上的数据将会被清空;理论上/dev/sda12上的数据不会有任何丢失。

    首先确保sda12没有被挂载,如果挂载了,使用umount卸载之,然后使用flashcache_create创建设备:

    ./flashcache_create cachedev /dev/sdb /dev/sda12

    如果是sudo帐号可能会遇到如下的报错: (more…)

  • 很多人都讨论了这个问题,参数innodb_thread_concurrency限制了InnoDB内部线程的数量。例如当有query需要InnoDB处理时,InnoDB首先会检查一下当前的内部线程数是不是超过了innodb_thread_concurrency的限制,如果超出则会让当前线程sleep一会儿,再试,如果还是受限,则会进入一个FIFO的队列。如果innodb_thread_concurrency设置成0表示,内部线程数量将不受限制(注:innodb_thread_concurrency值在不同的版本意义略有不同)。

    1. 该参数设置成多少合适?

    我不知道多大合适。我的经验值设置成64就够了,正常情况,应用并发不会超过这个值。

    如果设置成0,会让InnoDB的内部线程不受限制,如果你高并发的IO-bound的应用,很可能在InnoDB内部累计很多的并发等待IO的线程,主机的Load会很高,但是数据库依然会正常运行。

    从5.1.11开始这个值的默认值是8,意味着,InnoDB会限制内部线程数不超过8。如果是高并发的应用,你的MySQL能力可能会受到这个参数的限制。对于很多情况这个值有偏小的,并发量可能会比8大,这时参数innodb_thread_concurrency就会成为InnoDB的瓶颈。对于一个16核的系统,处理的并发很多时候都会大于8,而受cpu核数限制,太多的线程会在CPU切换上消耗过多资源。

    但是如果你系统并发量始终都是小于8的,那么设置成一个大于8的值并没有意义。

    2. 高并发下实验

    通过supersmack模拟了128个线程并发,做了5组对比测试:

    innodb_thread_concurrency

    最后,提一下,没事不要在生产环境动态更改innodb_thread_concurrency,很危险:Bug 40760

    参考:

    1. MySQL Manual

    2. MySQL: innodb_thread_concurrency beast

    3. do we still need innodb_thread_concurrency

    4. Mess with innodb_thread_concurrency

    5. InnoDB线程并发检查机制

    6. MySQL Bugs