Mysql运维记事

在创业公司做事儿,意味着随时都会遇到挑战。我虽然不是一个Mysql DBA,但还是得承担公司各个产品线、不同环境下的Mysql运维工作,好在现在数据量都不大,目前还能应付得过来。

在开始具体的运维工作之前,有两个基本原则先要阐述一下:

  1. 对于没有专门DBA人才的创业团队,能用云数据库(RDS)的,就尽量用云数据库。在计算机科学领域,数据库技术绝对算得上一个比较独立、深邃的学科,大型云厂商都有专业的、成规模的DBA团队,甚至是专门的数据库研发团队,他们打造的云数据库产品相对来说更加稳定,安全。比如说像AWS的RDS这种。直接用他们的产品,什么高可用、安全、备份问题基本是不用怎么操心。虽说人家是按使用时间来收费的,但也不是贵的离谱,相对于高级技术人员(DBA的工资一般都很高)的人力成本、服务器成本、托管费用来说,其实还算是便宜的。
  2. 如果受限于大环境(比如说云数据库一般版本比较低),必须要自己维护的数据库实例,一定要使用最新的5.7版。5.7版现在已经是GA版本了,相信我,这是Mysql历史以来最优秀的一个版本 — 性能、可用性、稳定性都达到了一个历史最高点。我们的应用有一个特殊的需求是中文分词+全文检索,这在5.7之前想直接通过数据库来做,是比较痛苦的。目前我们在5.7上面做的单表百万记录的中文全文检索,方便又快捷。

下面就简单记录一下,最近一段时间里面我在运维公司Mysql 5.7一主一从实例的过程中积累的经验。由于我司所有的服务都是运行在AWS云主机上,所有很多解决方案都是从云主机的角度来出发的。

  • AWS的Amazon Linux也是非常适合安装和运行Mysql实例的。以前我的第一反应是Mysql一定要在CentOS这种操作系统上运行,方便运维。事实证明,最新的Amazon Linux已经非常优秀的了,各种辅助设施也很完备,直接通过yum来安装和更新Mysql非常便捷。当然在通过yum安装mysql之前先要通过“yum localinstall”命令来安装最新的mysql yum源。我记得我使用的是“mysql57-community-release-el6-7.noarch.rpm”。具体的安装方法详见Mysql官网。有一个小插曲,在我装完mysql5.7.9并运行一个月以后,有一天不小心运行了一下“yum update”,结果就把mysql升级到了5.7.10。这个最新版的系统表和5.7.9有些不兼容,直接导致主从复制挂了,需要通过“mysq_upgrade”命令来在线修复这个问题。这个在数据库启动日志里面会得到提示。
  • 如何手动跳过基于GTID的主从复制过程中从库上执行失败的事务。我们的Mysql 5.7主从结构,从库比主库增加了更多的索引。这里需要说明一点就是,我们之所以做主从,是因为Mysql的Fulltext索引是非常消耗CPU和IO的,为了不影响主库的基本功能,我们选择只在从库建立全文检索,主库只负责数据更新。早期的时候由于没有限制死从库的数据库账户只具备读的权限,有开发人员会不小心在从库上做数据的更新,这样会导致主从两个库出现大量的数据不一致,主从复制线程在遇到在从库上执行失败的事务的时候hang住。Hang住的时候,通过“show slave status\G;”查看“Last_SQL_Error”执行哪个事务的时候出问题的。一般报错信息如下:

 

#Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 3 failed executing transaction 'c15bd334-7c7c-11e5-a5ab-02ce4164e0c5:206566' at master log mysql-bin.000008, end_log_pos 830470437. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.

然后通过下面的命令在主库上查看该事务所做的操作:

sudo mysqlbinlog --no-defaults --base64-output=DECODE-ROWS --verbose mysql-bin.000008 > /tmp/mysql-bin.000008.sql #导出该binlog文件里面所有的事务记录
通过grep或者vim /tmp/mysql-bin.000008.sql来找到"c15bd334-7c7c-11e5-a5ab-02ce4164e0c5:206566"这个gtid对于的事务是执行了什么操作

然后通过下面的一组命令,来跳过执行失败的事务:

STOP SLAVE;
SET @@SESSION.GTID_NEXT = 'c15bd334-7c7c-11e5-a5ab-02ce4164e0c5:206566';
BEGIN; COMMIT;
SET @@SESSION.GTID_NEXT = AUTOMATIC;
START SLAVE;

重复以上过程,直到从库的“Executed_Gtid_Set”跟上“Retrieved_Gtid_Set”为止。

  • 如何解决AWS RDS的时区问题。AWS的RDS目前是只提供5.6版本的数据库实例,并且很多参数是不允许使用者修改的,time_zone就是其中一个。云数据库嘛,这个参数不允许修改很正常。不过我们可以通过其他方案来解决这个问题。首先在数据库里面建立一个修改时区的sp,然后让每个连上上来的connection在初始化的时候执行这个sp,达到基于每个connection修改时区效果。插句题外话,时区问题其实并不是谁对谁错的问题,这个世界客观的时刻其实只有一个,数据库里面自动生成的时间一般都是UTC的,然后每个连接可以自己设置自己的时区,在取数据的时候mysql会自动根据connection携带的时区信息,把时间值做好时区转换再返回的。当然如果是自己运维数据库实例,可以通过设置time_zone的启动参数,让数据库在存数据的时候就把时区存成你想要的时区,取出来的时候就不需要关注转换的事情了。
-- 建立修改time_zone的sp
DELIMITER |

CREATE PROCEDURE mysql.store_time_zone ()

   IF NOT (POSITION('rdsadmin@' IN CURRENT_USER()) = 1) THEN

       SET SESSION time_zone = '+8:00';

   END IF

|

DELIMITER ;

-- 将sp的执行权限赋值给相应的用户

GRANT EXECUTE ON PROCEDURE mysql.store_time_zone TO 'cjj'@'%';

flush privileges;

-- 然后修改was rds的自定义参数
init_connect=CALL mysql.store_time_zone
  • 如何解决数据库文件损坏的问题。首先,数据库文件损坏的原因很难找到,从msyql自身的异常日志加上google也很难发掘出真正的损坏原因。mysql的异常日志一般这么描述的:
2015-12-15T13:07:06.049575-00:00 0 [ERROR] Error in Log_event::read_log_event(): 'read error', data_len: 8100, event_type: 30
...
2015-12-15T13:07:06.662616-00:00 6 [ERROR] InnoDB: trying to read page [page id: space=102, page number=3] in nonexisting or being-dropped tablespace
...
2015-12-15T13:07:06.667215-00:00 6 [ERROR] [FATAL] InnoDB: Unable to read page [page id: space=102, page number=3] into the buffer pool after 100 attempts. The most probable cause of this error may be that the table has been corrupted. Or, the table was compressed with with an algorithm that is not supported by this instance. If it is not a decompress failure, you can try to fix this problem by using innodb_force_recovery. Please see http://dev.mysql.com/doc/refman/5.7/en/ for more details. Aborting...
2015-12-15 13:07:06 0x7f5678208700 InnoDB: Assertion failure in thread 140009359312640 in file ut0ut.cc line 917
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
13:07:06 UTC - mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
Attempting to collect some information that could help diagnose the problem.
As this is a crash and something is definitely wrong, the information
collection process might fail.
...
2015-12-15T06:57:35.195773-00:00 0 [ERROR] InnoDB: Could not find a valid tablespace file for `news/FTS_000000
00000000074_00000000000000a9_INDEX_4`. Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-troubless
hooting-datadict.html for how to resolve the issue.

看到以上这些,基本就可以断定是数据库文件损坏了。按照提示,可以用forcing-innodb-recovery来解决问题。但是在直接修复之前,需要找到到底是哪个库,哪张表的文件损坏了,从日志的最后一行可以看出,最有可能出问题的数据库就是news这个库。然后可以通过”innochecksum”(5.7安装完以后这个命令就存在于/usr/bin下面找到具体是哪张表出问题了。找到mysql的data dir,执行下面的命令:

sudo innochecksum /var/lib/mysql/news/*.ibd

上面这条命令能告诉你到底是哪张表出问题了。然后通过下面的步骤来做修复:

#1,首先强制停止数据库,service mysqld stop不起作用的话用kill命令
#2,然后修改my.cnf,在mysqld的section下增加下面这个配置
innodb_force_recovery=1
#3,重新启动数据库
#4,通过mysqldum导出出问题的表的结构和数据
#5, 停止数据库
#6,修改my.cnf,改成innodb_force_recovery=3
#7,启动数据库
#8,删除出问题的表, 并重建
#9, 去掉innodb_force_recovery=3,或者innodb_force_recovery=0, 重启数据库
#10,一般来说这个时候数据库是能正常启动的,然后将之前dump出来的sql文件导入即可

当然如果通过修复单个表不能解决问题(有可能是多个表文件出问题了),可以将上面重建表的逻辑变成重建库的逻辑。
    • 给不同的用户授权不同数据库操作权限的时候,如果某数据库有sp,记得一定要将mysql.proc的只读权限带上。
grant all on news.* to 'cjj'@'10.0.%.%';
GRANT EXECUTE ON news.* TO 'cjj'@'10.0.%.%';
GRANT SELECT ON `mysql`.`proc` TO 'cjj'@'10.0.%.%';
flush privileges;

暂时就这些吧,后面再遇到问题解决了再把经验总结好写到这里来。

发表评论?

0 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>