聊聊,由于未加载tokudb引起造成Mysql主从同步失败的问题.
先听我说,我是个程序员,兼职部门的Mysql DBA . 部门里有好几个Mysql主从服务,每次做主从切换调换我都要欲仙欲死. 原本事不大,但每个库都要几个T大小.
今天原计划打算在程序里面做数据库主从读写分离,但发现他们的数据差异太大。 登上去一看,果然跟我预想的一样,同步出问题了。上次出过主从同步失败是因为网络问题。
.
文章写的不是很严谨,欢迎来喷,另外该文后续有更新的,请到原文地址查看更新。
.
先说下现在的Mysql关系,122是主,124是从服务器。 他们的主从关系虽然经过多次调换,但数据同步还是正常的。 但上次因为使用percona pt-online-change修改表结构的时出问题了。 由于pt-online-change每次修改字段都会创建一个新的临时表. 就是因为这个临时表… 这个新表是tokudb引擎,但是从数据库没有这个tokudb引擎,那么这问题的原因就好解释了.
#blog: http://xiaorui.cc 下面是报错的信息. mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 1.1.1.122 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.009427 Read_Master_Log_Pos: 90853169 Relay_Log_File: mysqld-relay-bin.001919 Relay_Log_Pos: 35392328 Relay_Master_Log_File: mysql-bin.004621 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1286 Last_Error: Error 'Unknown storage engine 'TokuDB'' on query. Default database: 'weixin_master'. Query: 'CREATE TABLE `weixin_master`.`_click_new` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `url` varchar(255) DEFAULT NULL, `title` text, `read_num` int(11) DEFAULT NULL, `like_num` int(11) DEFAULT NULL, `ts` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `read_num_idx` (`read_num`) USING BTREE, KEY `like_num_idx` (`like_num`) USING BTREE, KEY `ts_idx` (`ts`) USING BTREE, KEY `url_idx` (`url`) USING HASH ) ENGINE=TokuDB AUTO_INCREMENT=43541524 DEFAULT CHARSET=utf8 ROW_FORMAT=TOKUDB_LZMA' Skip_Counter: 0 Exec_Master_Log_Pos: 35392165 Relay_Log_Space: 658669766712 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 1286 Last_SQL_Error: Error 'Unknown storage engine 'TokuDB'' on query. Default database: 'weixin_master'. Query: 'CREATE TABLE `weixin_master`.`_click_new` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `url` varchar(255) DEFAULT NULL, `title` text, `read_num` int(11) DEFAULT NULL, `like_num` int(11) DEFAULT NULL, `ts` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `read_num_idx` (`read_num`) USING BTREE, KEY `like_num_idx` (`like_num`) USING BTREE, KEY `ts_idx` (`ts`) USING BTREE, KEY `url_idx` (`url`) USING HASH ) ENGINE=TokuDB AUTO_INCREMENT=43541524 DEFAULT CHARSET=utf8 ROW_FORMAT=TOKUDB_LZMA' Replicate_Ignore_Server_Ids: Master_Server_Id: 122 Master_UUID: 5a2995e1-9cb6-11e5-8b6b-44a8422bfd3f Master_Info_File: /ssd/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 151214 15:26:01 Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 1 row in set (0.00 sec) ERROR: No query specified
解决的方式很简单,干掉从服务器,然后安装含有tokudb引擎的MariaDB mysql server.
MariaDB在5.5.41开始就内置了Tokudb引擎,貌似mariadb 10更加简单了,在配置文件中打开注释就可以了。
vim mariadb.repo
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
yum install MariaDB-server MariaDB-client -y
我们编辑下文件,在配置文件里加入so插件的支持。 vim /etc/mysql/conf.d/tokudb.cnf:
plugin-load-add=ha_tokudb.so
重启数据库
$ sudo service mysql restart
如果启动时候报错,请查看/var/log/mysql.err错误日志。
如果遇到这个问题 [ERROR] TokuDB will not run with transparent huge pages enabled.
另外我们需要注意一个内核参数, 一定要确保他是never状态。
$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
我们在同步数据库之前需要冷静一下. 我上次修改表结构或许是11月份,而现在的时间已经是1月份中旬了,查看了下主的binlog保留时间,确定主my.cnf的expire_logs_days是20天。 难道要重做主从? 这么大的数据光是copy就要好长时间的.
最后通过多方查资料,明白一个Mysql同步的那些事。 Mysql从服务器会启动两组线程,Slave_IO_Running 是负责同步binlog,slave_sql_running是负责把sql语句执行到本地. 当slave_sql_running因为各种原因出错时,Slave_IO_Running是不受影响的,照常传输binlog。
当我重新start slave的时候,遇到一个问题slave_sql_running no的问题…
话说如果slave_sql_running no了,那么也有两种可能,
1.程序可能在slave上进行了写操作
2.也可能是slave机器重启后,事务回滚造成的,这也是mysql的一种自我保护的措施,像关键时候只读一样。
一般是事务回滚造成的:
mysql> stop slave;
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave;
总结,一定要细心看文档. 数据库要统一版本,我这就因为没有统一Mysql的版本,倒是有的Mysql是有Tokudb,有些没有.
建议使用Gtid 同步,会省去好多麻烦.