我在两台机器之间的 MySQL 5.5 复制性能方面遇到了一个严重的问题,主要是带有基于语句的复制的 myISAM 表。二进制日志和 mysql 数据目录都位于同一个 Fusion ioDrive 上。
这个问题是最近的一个大问题,当时我们需要暂停复制大约。3小时。在没有其他负载的情况下再次赶上大约需要 10 个小时。
如何提高复制的性能?机器 B 基本上处于空闲状态(很少,IO,16 个内核中有 2 个已用尽,大量空闲 RAM),因为只有 1 个 mySQL 线程在写入数据。以下是我的一些想法:
- 切换到基于行的复制。在测试中,这仅产生了 10-20% 的性能提升
- 使用多线程复制升级到 mySQL 5.6。我们可以轻松地将数据拆分到单独的数据库中,基准测试似乎表明这会有所帮助,但代码似乎还没有准备好生产。
- 一些有助于加快复制速度的配置变量
主要问题是,如果在暂停 3 小时后需要 10 小时才能赶上,这意味着复制正在 10 小时内写入 13 小时的数据,或者能够以传入数据速度的 130% 写入。我期待至少在不久的将来在 Master 机器上进行双写,因此迫切需要一种提高复制性能的方法。
机器A:
- 掌握
- 24GB内存
- 1.2TB 融合 ioDrive2
- 2 个 E5620
- 千兆互连
my.cnf
:
[mysqld]
server-id=71
datadir=/data_fio/mysqldata
socket=/var/lib/mysql/mysql.sock
tmpdir=/data_fio/mysqltmp
log-error = /data/logs/mysql/error.log
log-slow-queries = /data/logs/mysql/stats03-slowquery.log
long_query_time = 2
port=3306
log-bin=/data_fio/mysqlbinlog/mysql-bin.log
binlog-format=STATEMENT
replicate-ignore-db=mysql
log-slave-updates = true
# Performance Tuning
max_allowed_packet=16M
max_connections=500
table_open_cache = 2048
max_connect_errors=1000
open-files-limit=5000
# mem = key_buffer + ( sort_buffer_size + read_buffer_size ) * max_connections
key_buffer=4G
max_heap_table_size = 1G
tmp_table_size = 4G
myisam_sort_buffer_size = 256M
sort_buffer_size=4M
read_buffer_size=2M
query_cache_size=16M
query_cache_type=2
thread_concurrency=32
user=mysql
symbolic-links=0
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[mysql]
socket=/var/lib/mysql/mysql.sock
[client]
socket=/var/lib/mysql/mysql.sock
机器 B:
- 奴隶
- 36GB内存
- 1.2TB 融合 ioDrive2
- 2 个 E5620
- 千兆互连
my.cnf
:
[mysqld]
server-id=72
datadir=/data_fio/mysqldata
socket=/var/lib/mysql/mysql.sock
tmpdir=/data_fio/mysqltmp
log-error = /data/logs/mysql/error.log
log-slow-queries = /data/logs/mysql/stats03-slowquery.log
long_query_time = 2
port=3306
# Performance Tuning
max_allowed_packet=16M
max_connections=500
table_open_cache = 2048
max_connect_errors=1000
open-files-limit=5000
# mem = key_buffer + ( sort_buffer_size + read_buffer_size ) * max_connections
key_buffer=4G
max_heap_table_size = 1G
tmp_table_size = 4G
myisam_sort_buffer_size = 256M
sort_buffer_size=4M
read_buffer_size=2M
query_cache_size=16M
query_cache_type=2
thread_concurrency=32
user=mysql
symbolic-links=0
plugin-load=archive=ha_archive.so;blackhole=ha_blackhole.so
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[mysql]
socket=/var/lib/mysql/mysql.sock
[client]
socket=/var/lib/mysql/mysql.sock
哇,你有一些非常强大的硬件来解决这个问题。除了升级到 Sandy/Ivy Bridge CPU 以获得 Btree 搜索等 20-50% 更好的性能外,你可以在硬件方面投入更多。
请注意,我的强项是 Innodb,所以我要
Innodb 可以通过将这些经常访问的行存储在其缓冲池中来帮助充分利用所有内存。您可以将它调整到您想要的大小(比如 80% 的内存)并且新的读/写保留在内存中,直到它需要将它们推送到磁盘以便为最新访问的数据腾出更多空间。在内存中比您的 FusionIOs 快一个数量级。
还有许多 Innodb 特性,例如自适应哈希、自动 inc 锁定机制等,它们可以为您的环境带来好处。但是,您比我更了解您的数据。
在 innodb 的世界里,一个好的短期解决方案是优化你的从服务器——你真的需要你的从服务器上的每一个索引,就像你的主服务器上的一样吗?索引是插入/更新/删除的链条,即使使用 Fusion IO 卡也是如此。IOPS 并不是这里的一切。Sandy/Ivy bridge procs 具有更好的内存吞吐量和计算性能 - 它们可以使您现在拥有的 Westmeres 产生巨大的变化。(总体图 20-50%)。删除从站不需要的所有索引!
其次,几乎肯定只适用于 innodb,mk-prefetch 可以知道哪些更新以及在从属写入它们之前。这允许 mk-prefetch 首先运行读取查询,从而在单个 repl 运行写入查询时强制数据在内存中。这意味着数据在内存中而不是在 fusionIO 中,这是一个快速数量级的性能提升。这产生了巨大的差异,超出了人们的预期。许多公司将其用作永久解决方案。查看Percona Toolkit了解更多信息。
第三,也是最重要的一点,一旦您升级到 Innodb,一定要检查 Tokutek。这些家伙有一些非常棒的东西,远远超过了 Innodb 的写入/更新/删除性能。他们将改进的复制速度吹捧为主要优势之一,您可以从他们的基准测试中看出为什么 Fusions 疯狂的 IOPS在 Btrees 的情况下仍然无济于事。(注意:未经我独立验证。)他们使用 btree 索引的直接替换,虽然复杂得可怕,但改善了 btree 索引的许多算法速度限制。
我正在考虑采用 Tokutek。如果他们释放了如此多的写入速度,那我就可以添加更多索引。由于他们以如此美妙的比率(他们引用的 25 倍)压缩数据和索引,您甚至不需要为增加的数据支付(性能、维护)价格。不过,您确实需要为他们的引擎付费($),每预压缩 GB 每年 2500 美元,IIRC。如果您复制了数据,它们会提供折扣,但您甚至可以只在您的从服务器上安装 Tokutek,而让您的主服务器保持原样。查看麻省理工学院算法公开课件讲座中的技术细节。或者,他们的博客上有大量技术资料,并为那些没有 1:20 观看视频的人定期提供白皮书。我相信该视频还给出了读取速度的 Big-O 公式。我有假设读取速度较慢(总有一个权衡!),但公式太复杂了,我无法衡量多少。他们声称大致相同,但我宁愿理解数学(不太可能!)。你可能比我更容易发现这一点。
Ps 我不隶属于 Tokutek,我从未运行过他们的产品,他们甚至不知道我在看他们。
更新:
我看到你在这个页面上还有其他问题,我想我会插话:
首先,slave pre-fetch 几乎肯定不会对 myisam 起作用,除非你有一个特殊的环境。这主要是因为预取将锁定您打算写入的表,或者从属线程已锁定预取守护进程所需的表。如果您的表在复制方面非常平衡,并且以循环方式写入不同的表,这可能会起作用——但请记住,这是非常理论化的。“高性能 Mysql”一书在“复制问题”部分有更多信息。
其次,假设您的从属负载为 1.0-1.5,如果您有其他进程或查询正在运行但基线为 1.0,则负载可能更高。这意味着您可能受 CPU 限制,这很可能与您的 FusionIO 板载有关。正如我之前提到的,Sandy/Ivy Bridge 会带来更多魅力,但可能不足以让您以最小的延迟度过艰难时期。如果这个从站的负载主要是只写的(即没有多少读取),你的 CPU 几乎肯定会花时间计算 btree 插入/删除的位置。这应该强化我上面关于删除非关键索引的观点——您可以随时重新添加它们。禁用超线程是行不通的,更多的 CPU 不是你的敌人。一旦你的内存超过 32GB,比如 64GB,你就需要担心内存分配问题,但即便如此,症状也有所不同。
最后,也是最重要的(不要跳过这一部分;)),我假设您现在正在运行 RBR(基于行的复制),因为您提到切换它时性能会显着提高。但是 - 可能有一种方法可以在这里获得更高的性能。如果您复制的表没有主键,则可能会出现Mysql 错误 53375 。slave 基本上不够聪明,只能使用主键,因此缺少主键会迫使复制线程为每次更新进行全表扫描. 修复方法是简单地添加一个良性的代理自动递增主键。我只会在表很大时才这样做(比如几千行或更大)。当然,这是以在表上有另一个索引为代价的,这会增加您在 CPU 上付出的代价。请注意,反对这一点的理论论据很少,因为如果您不这样做,InnoDB 会在幕后添加一个。然而,幽灵并不是防御 53375 的有效方法。Tungsten 也可以解决这个问题,但您需要确保在使用 Tungsten 时您的编码是直接的。上次我玩它时,当需要复制任何非 UTF8 字符串时,它会死得很惨。那是我放弃它的时候。
不是答案,但您可以考虑使用钨复制器及其商业产品以获得更大的灵活性。瓶颈是单核 100%cpu 使用率吗?
因此,如果您在从站上进行备份……并且您使用 myiasm 表……您将锁定表以进行备份以防止损坏。所以在备份完成之前复制无法工作.. 然后它赶上了。