分类目录归档:mysql

表迁移工具的选型-mysqlpump

1.1. 场景

有两种场景适合使用逻辑迁移:伪大表、跨产品迁移(MySQL 到 MSSQL)。

下面我们模拟伪大表的进行表迁移的情况。

1.2. 使用工具

mysqlpump

1.3. 为什么选mysqlpump

没有什么别的原因就是因为图新,mysqlpump这个工具是在MySQL5.7才才出来的,在备份库的时候能做到多线程备份。其实,备份单表我更加推荐使用mydumper。当是个人认为mysqlpump以后也会有很多人选择的。就先Oralce的dump代替exp一样。

官网:http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html

1.4. 制造出大表假象

下面制造的数据量点大,可能要花费你一点时间,你可以更具磁盘情况来减少一些数据:

查看数据大小情况(磁盘上的数据大小)

查看真实的大小情况

从上面可以看出在磁盘上的数据大小是12G,而实际的大小才0.01562500MB(估计值),在种情况使用逻辑迁移是再好不过的了。

1.5. mysqlpump的使用

上面会生成 t1.sql 表数据文件

1.6. 将数据迁移到 test2库中

1.7. 总结

很明显在上面的情况如果使用物理迁移那将会需要比较长的时间。当然如果你遇到了伪大表的情况,这时候就应该向老大申请时间,重新创建这张表的数据了。在实际工作当中增删改平凡的表就容易出现这样的情况。

 

昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)

感觉本文内容不错,读后有收获?

逛逛衣服店,鼓励作者写出更好文章。

Inception 审核规范及原则(7)

写在前面的话

MySQL语句的审核,在业界都已经基本被认同了,实际上也是对MySQL语句写法的统一化,标准化,而之前的人工审核,针对标准这个问题其实是很吃力的,标准越多,DBA越累,开发也越累。那么Inception出现之后,它是不怕标准多的,只要DBA定义了为了更好的管理数据库的规则时,Inception就可以很好的执行,并且返回审核结果,那么这一章主要介绍当前Inception在审核时,是使用什么样的规则来做的,并且哪些规则是可以配置的,哪些规则是不可以配置的,这样针对不同的部门或者公司,可以定制不同的规则,而配置参数将在<<Inception所支持的参数变量>>中详细介绍。

下面就是有关审核规范的具体信息,但一些人为的或者逻辑的东西机器没办法搞定的,需要我们DBA自己定义,所有制定的规则,都是以语法正确为前提的,当然首先审核的就是语法问题,如果语法不通过,则整个语句块中,语法出问题的位置前面的语句审核完成,后面则不能将各个语句分开,报错时后面就被认为是一个语句。

重要声明:下面所列出来的规则,不一定能覆盖所有Inception当前已经实现的功能,具体包括什么规则,还需要在使用过程中总结,发现,同时可以结合配置参数来详细了解这些规则。

支持的语句类型

  • use db:此时会检查这个库是不是存在,需要连接到线上服务器来判断。
  • set option:现在只需要支持set names charset,设置其它变量时都报错不支持。
  • 创建数据库语句
  • 插入语句(包括多值插入)
  • 查询插入语句
  • 删除语句(包括多表删除)
  • 更新语句(包括多表更新)
  • 创建表语句
  • 删除表语句
  • 修改表语句
  • Truncate表语句
  • inception命令集语句(包括管理命令)

插入语句检查项

  • 表是否存在
  • 必须指定插入列表,也就是要对哪几个列指定插入值,如insert into t (id,id2) values(…),(可配置)
  • 必须指定值列表,与上面对应的列,插入的值是什么,必须要指定。
  • 插入列列表与值列表个数相同,上面二者的个数需要相同,如果没有指定列列表(因为可配置),则值列表长度要与表列数相同。
  • 不为null的列,如果插入的值是null,报错(可配置)
  • 插入指定的列名对应的列必须是存在的。
  • 插入指定的列列表中,同一个列不能出现多次。
  • 插入值列表中的简单表达式会做检查,但具体包括什么不一一指定

更新、删除语句检查项

  • 表是否存在
  • 必须有where条件(可配置)
  • delete语句不能有limit条件(可配置)
  • 不能有order by语句(可配置)
  • 影响行数大于10000条,则报警(数目可配置)
  • 对WHERE条件这个表达式做简单检查,具体包括什么不一一指定
  • 对更新列的值列表表达式做简单检查,具体不一一指定
  • 对更新列对象做简单检查,主要检查列是不是存在等
  • 多表更新、删除时,每个表必须要存在

建表语句检查项

表属性的检查项

  • 这个表不存在
  • 对于create table like,会检查like的老表是不是存在。
  • 对于create table db.table,会检查db这个数据库是不是存在
  • 表名、列名、索引名的长度不大于64个字节
  • 如果建立的是临时表,则必须要以tmp为前缀
  • 必须要指定建立innodb的存储引擎(可配置)
  • 必须要指定utf8的字符集(字符串可配置,指定支持哪些字符集)
  • 表必须要有注释(可配置)
  • 表不能建立为分区表(可配置)
  • 只能有一个自增列
  • 索引名字不能是Primay
  • 不支持Foreign key(可配置)
  • 建表时,如果指定auto_increment的值不为1,报错(可配置)
  • 如果自增列的名字不为id,说明有可能是有意义的,MySQL这样使用比较危险,所以报警(可配置)

列属性的检查项

  • 不能设置列的字符集(可配置)
  • 列的类型不能使用集合、枚举、位图类型。(可配置)
  • 列必须要有注释(可配置)
  • char长度大于20的时候需要改为varchar(长度可配置)
  • 列的类型不能是BLOB/TEXT。(可配置)
  • 每个列都使用not null(可配置)
  • 如果列为BLOB/TEXT类型的,则这个列不能设置为NOT NULL。
  • 如何是自增列,则使用无符号类型(可配置)
  • 如果自增列,则长度必须要大于等于4个字节(可配置)
  • 如果是timestamp类型的,则要必须指定默认值。
  • 对于MySQL5.5版本(包含)以下的数据库,不能同时有两个TIMESTAMP类型的列,如果是DATETIME类型,则不能定义成DATETIME DEFAULT CURRENT_TIMESTAMP及ON UPDATE CURRENT_TIMESTAMP等语句。
  • 每个列都需要定义默认值,除了自增列、主键列及大字段列之外(可配置)
  • 不能有重复的列名

索引属性检查项

  • 索引必须要有名字
  • 不能有外键(可配置)
  • Unique索引必须要以uniq_为前缀(可配置)
  • 普通索引必须要以idx_为前缀(可配置)
  • 索引的列数不能超过5个(数目可以配置)
  • 表必须要有一个主键(可配置)
  • 最多有5个索引(数目可配置)
  • 建索引时,指定的列必须存在。
  • 索引中的列,不能重复
  • BLOB列不能建做KEY
  • 索引长度不能超过766
  • 不能有重复的索引,名字及内容

默认值检查项

  • BLOB/TEXT类型的列,不能有非NULL的默认值
  • MySQL5.5以下(含)的版本,对于DATETIME类型的列,不能有函数NOW()的默认值。
  • 如果设置默认值为函数,则只能是NOW()。
  • 如果默认值为NULL,但列类型为NOT NULL,或者是主键列,或者定义为自增列,则报错。
  • 自增列不能设置默认值。

修改表语句检查项

  • 表是不是存在

创建索引检查项

  • 同上面创建表中的索引检查项

加列检查项

  • 同上面创建表中的列检查项

修改表检查项

  • 表是不是存在
  • 如果语句块中存在多条对同一个表的修改语句,则建议合并成一个ALTER语句
  • 列是否存在
  • 剩下的同上面创建表,创建索引,创建列,默认值等检查项一样

删除索引检查项

  • 表是不是存在
  • 检查索引是不是存在

修改列的默认值检查项

  • 同默认值检查项

修改表属性

  • 表属性只支持对存储引擎、表注释、自增值及默认字符集的修改操作。
  • 修改存储引擎时检查是不是Innodb(可配置)。
  • 字符集修改检查是不是属于设置参数的值(支持字符集可配置)。

转换表字符集

  • 字符集修改检查是不是属于设置参数的值(支持字符集可配置)。

声明

  • 针对线上MySQL服务器是不是5.6以上(包含)版本,有不同的处理策略,比如在预估影响行数时,5.6可以直接对任何DML语句做EXPLAIN操作,而在5.5版本中,只支持对SELECT语句执行EXPLAIN操作,而在5.5版本中,有些DML语句是不容易直接转换为SELECT语句去做EXPLAIN,这样导致预估行数为0。
  • 还是针对5.6以上版本与5.5版本的不同,DATETIME、TIMESTAMP系列类型在执行时,5.5的限制比较多,而5.6基本通用,所以这上面的处理可能在5.6及5.5版本上,相同语句返回的结果集是不同的(规则是在5.5中以在执行时报的错误信息为准),这与线上版本有关系。

Inception命令集语句(10)

Inception命令是一个Inception所支持的一系列命令集,为了与原MySQL的命令区分,在命令前面使用Inception这个新的关键字。

这个命令集包括的功能有:打印线上服务器的一些信息,支持所有show命令,只要在原来show命令前面加上inception即可,返回的结果集放在上面所述结果集的SQL列中,前面是当前执行的inception命令,以冒号分隔,后面接着是执行show命令得到的结果集,每行以换行符分隔,一行中的不同列的数据,以竖线“|”分隔。此外还包括上面设置或查看相关参数的三个命令,这三个命令只能通过MySQL客户端或者编程直接执行,而不需要加上数据源、标记语句等信息。因为它是对Inception本身进行操作的。

下面列举一下共包括哪几类:

显示远程变量

这种情况,语法为inception {MySQL支持的原生的show命令};,比如

其实这个命令就是用来方便得通过Inception工具来查看线上的某些状态或者变量等信息的,返回的结果会放在后面将要介绍的<<Inception结果集>>中所说的结果集的SQL列中的。具体输出格式是,最前面还是输出执行的inception命令,然后以冒号分隔,冒号后面接着是执行show命令得到的结果集,每行以换行符分隔,一行中的不同列的数据,以竖线“|”分隔。 比如对于命令

返回结果如下:

注意:因为查看远程变量,是需要连到远程数据库服务器的,所以执行时还是必须要加上前面的数据源信息的,不然在MySQL客户只支持这个语句会报错。 mysql这个就是在提醒,必须要放在inception_magic_startinception_magic_commit语句中才能执行。

显示本地全部变量

显示本地全部变量,就是查看Inception本身所有参数的值,语法非常简单:

输出就是所有的变量,下图所示为部分变量: mysql注意,这个命令只显示Inception本身的一些参数变量的值,那么是不需要数据源信息的,所以它是可以直接在MySQL客户端执行的。

显示本地某个变量

显示本地某个变量,和上面唯一的区别是,这只显示一个变量的值,而上面是显示全部,语法:

下面是图例: mysql

注意,这个命令只显示Inception本身的一些参数变量的值,那么是不需要数据源信息的,所以它是可以直接在MySQL客户端执行的,而如果放在数据源信息中执行的话,这样的语句会被忽略,不会做任何处理。

设置本地变量

Inception不仅可以查看它的参数值,还可以通过语句动态设置某个参数的值,因为Inception的参数(除部分OSC参数,具体参见<<Inception所支持的参数变量>>)是全局的,并且不是会话级别的,所以它是设置之后马上生效的,而有些OSC的参数是会话的,则只影响当前执行的连接。语法为:

注意,这个命令只显示Inception本身的一些参数变量的值,那么是不需要数据源信息的,所以它是可以直接在MySQL客户端执行的,而如果放在数据源信息中执行的话,这样的语句会被忽略,不会做任何处理。 下面是图例:

mysql

显示OSC执行进度

这个语句的作用是,当某一个ALTER TABLE语句正在通过Inception使用OSC执行时,可以通过这个语句来查询执行的进度度信息,语法:

具体的细节会在后面专门的一章<<Inception 对OSC的支持>>中讲述,这里只看一下图例: mysql

上面是正在做的,而如果语句块中有多个修改表的操作,则前面的会看到执行完成的进度信息: mysql

查看当前processlist

inception还可以查看当前正在执行的所有线程信息,语法为:

mysql当前命令执行之后,返回的结果信息如上图所示,每一个列介绍如下:

  1. id:一个简单的计数。
  2. dest_user:表示当前执行语句访问数据库时所用的用户名。
  3. dest_host:表示当前执行语句要访问的数据库地址。
  4. dest_port:表示当前执行语句要访问的数据库的端口。
  5. from_host:表示当前执行语句是从机器上发起的。
  6. command:表示当前执行的是什么操作,包括CHECK(简单审核),EXECUTE(执行),SPLIT(拆分),PRINT(打印计划树),LOCAL(本地命令)。
  7. state:表示在当前命令下,执行的状态是什么,状态包括INIT(初始阶段),CHECKING(正在审核),EXECUTING(正在执行),DEINIT(退出),BACKUP(正在备份)。
  8. time:表示当前语句执行所用时间。
  9. info:显示当前正在执行的语句。

ELK 处理 Percona 审计日志(填坑)

前提

1、有强烈的审计需求。

2、能允许10%-15%左右的性能损失。

3、有强烈的对数据库操作实时查看需求(一般都是为了领导要求)。

Logstash 比较坑的配置

上面的配置看上去是没有问题的,如果是一般的json数据哪就能解析成功了,

但是在 Percona audit plugin 中应用程序应用程序生成的SQL是五花八门,各种字符都有其中有。

如下审计的日志被 python 读取后的字符串展现(红色标记):

ELK

从上图可以看到有一些换行后tab的字符,这些字符使用 json.load 的时候会报错,不能解析成json

使用python json 模块解析相关日志文件报错:

所以在使用logstash的时候也就解析不了这样的json数据了,

最终logstash只能报错并将整个message记录到 Elasticsearch 中

解决办法

解决办法就是把这些字符替换掉。如下 Logstash 配置文件

该配置文件是投机取巧的办法, 把 (换行/tab) 字符替换成空格,要注意的一点最终显示的SQL和原来的有所差别。

这种方法有点不灵活如果sql语句中还有遇到一些json不能解析的字符又要进行处理。

>>朋友们如果有更好的方法也告知一声哈!<<<

还不能笑到最后

刚开始以为这一切都万事大吉了。其实还有个一坑就是在使用 Kibana 查看的时候,这时候问题就来了。

有是有过 Percona audit 插件的估计都有这样的问题,就是他记录的是时间是国际形式的(如上图黄色标记),不像我们习惯了北京时间。因此在页面显示的时间会比我们平时的少 8 小时。

一般来说在ELK中使用国际的标准格式是合理的。因为在使用 Kibana 查看的时候会帮你自动转化成本地时间格式。也就是如果我们在中国他会自动把 timezone 转化为 Asia/Shanghai(东8区) 的。所以显示的时间应该是正确的才对。可是实际情况并没有。

没有转化的原因

是应为 Elasticsearch 将 “2016-08-30T01:45:30 UTC” 这串字符解析成了String类型。按道理应该解析成和@timestamp一样的date类型。

解决思路

将 “2016-08-30T01:45:30 UTC” 格式转化成和 @timestamp 一样的格式(“2016-08-30T01:45:30Z”)

最终配置文件如下

使用上面配置就能顺利的将 时间格式 转化成 Elasticsearch 想要的时间格式,并且能在 Kibana 中正确显示。

祝大家好运。

 

昵称: HH

QQ: 275258836

ttlsa群交流沟通(QQ群②: 6690706 QQ群③: 168085569 QQ群④: 415230207(新) 微信公众号: ttlsacom)

感觉本文内容不错,读后有收获?

Inception 备份功能说明(6)

上面已经提到,Inception在做DML操作时,具有备份功能,它会将所有当前语句修改的行备份下来,存储到一个指定的库中,这些库的指定需要通过几个参数,它们分别是:

  • inception_remote_backup_host //远程备份库的host
  • inception_remote_backup_port //远程备份库的port
  • inception_remote_system_user //远程备份库的一个用户
  • inception_remote_system_password //上面用户的密码

这些参数可以直接在命令行中指定,也可以用–defaults-file指定一个my.cnf文件,一经指定,再不能更改,除非将服务器关闭,修改之后再次启动。文件中指定这几个参数的值,用法与mysql是相同的。 另外:为了使备份成为一个可选功能,增加一个是不是备份的参数–enable-remote-backup(在前面<<Inception支持选项及意义>>一章中已经介绍过),如果开启则不做备份操作,都是直接执行,另外还有一点,执行时被影响的表如果没有主键的话,就不会做备份了,这样更简单并且备份时间及数据都会少一点,不然回滚语句的WHERE条件就会将所有列写进去,这样会影响性能且没有太大意义,所以在WHERE条件中,只需要主键即可。

通过上面参数设置的Inception备份用户必须要具备下面的权限才能成功备份的,包括:CREATE、INSERT。CREATE权限用于创建表或者库的,INSERT权限用于插入备份数据的,其它的权限不需要(也许是暂时的)。

备份数据在备份机器的存储,是与线上被修改库一对一的。但因为机器的多(线上机器有很多)对一(备份机器只有一台),所以为了防止库名的冲突,备份机器的库名组成是由线上机器的 IP 地址的点换成下划线,再加上端口号,再加上库名三部分,这三部分也是通过下划线连接起来的。例如:192_168_1_1_3310_inceptiondb,下面用 inceptiondb 举例为线上库名。

针对一个备份库,里面的表与对应线上表都是一一对应的,也就是说线上库inceptiondb中有什么表,在备份库192_168_1_1_3310_inceptiondb中就有什么表,表名也完全相同,不同的只是表中的列不同而已,它是用来存储所有对这个表修改的回滚语句的, 对应的表包括的列主要有下面两个:
rollback_statement text:这个列存储的是针对当前这个表的某一行被修改后,生成的这行修改的回滚语句。因为 binlog 是 ROW 模式的,所以不管是什么语句,产生的回滚语句都是针对一行的,同时有可能一条语句的修改影响了多行,那么这里就会有多个回滚语句,但对应的是同一个 SQL 语句。对应关于通过下面的列来关联起来。
opid_time varchar(50):这个列存储的是的被执行的 SQL 语句在执行时的一个序列号,这个序列号由三部分组成:timestamp(int 值,是语句被执行的时间点),线上服务器执行时所产生的 thread_id,当前这条语句在所有被执行的语句块中的一个序号。产生结果类似下面的样子:1413347135_136_3,针对同一个语句影响多行的情况,那么所产生的多行数据中,这个列的值都是相同的,这样就可以找到一条语句对应的所有被影响数据的回滚语句。

除了与原库中的表一一对应之外,每个备份库中还有另外一个表:$_$Inception_backup_information$_$,这就是表名,非常难看,主要是为了防止与原线上库中的表名发生冲突。这个表是用来存储所有对当前库操作的操作记录的,它是公用的,对线上这个库的所有表操作记录都存储在这里面,这个表的结构如下: mysql

而线上库表结果与备份库表结构的对应关系是: mysql

各个列的解释:


opid_time:这个列其实与上面备份表中的列 opid_time 是对应的,这里面存储的每一条记录对应语句块中被执行的一条 SQL 语句,opid_time 就是根据这条语句所生成的,那么一条语句有可能产生多行的影响,那么上面回滚语句表中的多行或者一行对应这个公共表的一行,这样就对上了。
start_binlog_file:这个列从名字就可以看出,表示的是执行这条语句前 binlog 所在位置的文件名,当然这个值不一定准确,因为这是在执行语句前通过show master status;语句来获取的,那么在数据库并发比较高的话,这个值一般都不是准确的当前语句的Binlog开始位置,这个位置只能是这个语句产生的Binlog前面某个位置,同理下面三个位置信息也是一样。
start_binlog_pos:这个列与上面的列对应,表示的是上面指定文件的位置信息。
end_binlog_file:这个列表示的是执行当前语句之后,binlog 所在的文件名。
end_binlog_pos:这个列与上面的列对应,它表示执行完成之后,binlog 在文件end_binlog_file中的偏移位置。
sql_statement:这个列存储的是当前这个被执行的SQL 语句。
host:表示在什么地址执行了这条语句。
dbname:在哪个库中执行了这个语句。
tablename:表示当前语句影响的表的表名。可以通过这个名字来对应到备份表名。
port:与 host 对应,表示执行时数据库的端口是什么。
time:表示当前语句的执行时间。
type:表示操作类型,现在只支持INSERT、UPDATE、DELETE、CREATEDB、CREATETABLE、ALTERTABLE、DROPTABLE等类型。


针对现在备份及回滚的实现方案,如果已经知道一个语句的执行序列,想拿到这个语句的回滚语句,要执行的 SQL 语句为:

上面语句查出来的只是针对一个语句块中某一条语句的回滚语句,但是如果想要得到整个语句块的回滚语句,还需要在这基础上做二次开发,针对每条语句的回滚(包括多条回滚语句)语句的前后,加上事务,保证这个回滚是原子的,并且按照执行结果的最后一个列的倒序将回滚语句排序,这样查出来的就是完整的回滚语句。

关于 DDL 的回滚,其实是很难做得完美,因为涉及到数据的大批量更改,并且 binlog 也是语句模式的,所以很难处理,但在 Inception 中采取的策略是只处理定义,不处理数据。现在 DDL 操作的回滚只包括 CREATE TABLE 、ALTER TABLE、DROP TABLE,其它类型的操作不支持,并且也没有太大意义,在实际使用中如果有需求再考虑如何实现。

每条 DDL 语句算是一个操作,同样的,这个操作也会存储在表$_$Inception_backup_information$_$中,关于 binlog 的一些列没有实际意义,对应的 opid_time 与 DML 是相同的,而同时在被操作表中,存储了回滚语句,其中的列 opid_time与上面表中的这个列关联。一个 DDL 操作(不管其中做了多少事),对应的回滚语句也是一条语句,例如: 原来的表是这样的:

要执行的 alter 表语句为:

那么产生的回滚语句为:

 

Inception结果集(9)

Inception给用户返回的信息有两种,一种是提交给Inception的基础信息存在错误,比如源信息不全,或者源信息有错误等,这种情况下,直接报异常,包括错误码及错误信息,与MySQL服务器的异常是一样的,在外面正常处理即可。 如果没有上面的问题,都会以结果集的方式将检查结果告诉客户端。这种方式非常友好,在它的基础上用现有的成熟的接口处理起来非常方便。返回的结果集中,每一个行数据,就是一条提交的SQL语句,Inception内部将所有提交的语句块一条条的拆开,以结果集的方式返回,针对每一条语句,有什么问题或者状态,在结果集中是一目了然。

需要注意的是,如果在语句中出现语法错误,则不能继续了,因为Inception已经不能将剩下的语句分开了,那么此时前面已经正常检查的多行为多个结果集的行返回,后面出错的语句为一行返回,当然这个的错误信息是语法错误。 Inception返回结果集的结构如下:

  1. ID:用来表示检查的sql序号的,每次检查都是从1开始。
  2. stage:这个列显示当前语句已经进行到哪一步了,包括CHECKED、EXECUTED、RERUN、NONE,NONE表示没有做过任何处理,有可能前面有语法错误直接就提前返回了, CHECKED表示这个语句只做过审核,而没有再进行下一步操作,EXECUTED表示已经执行过,如果执行失败,也是用这个状态表示,RERUN表示的是,对于影响上下文的语句,已经执行成功,但为了与EXECUTED区分,用RERUN表示,主要是因为在执行过程中,如果某一条语句执行失败了,则上层可能需要将没有执行的语句提取出来,再次执行,那么影响上下文的语句是需要加上的,所以用RERUN来表示。影响上下文的语句一般包括set names和use db这两种,而当前Inception支持的只有这两种。
  3. errlevel:返回值为非0的情况下,说明是有错的。1表示警告,不影响执行,2表示严重错误,必须修改。
  4. stagestatus:用来表示检查及执行的过程是成功还是失败,如果审核成功,则返回 Audit completed。如果执行成功则返回Execute Successfully,否则返回Execute failed,如果备份成功,则在后面追加Backup successfully,否则追加Backup failed,这个列的返回信息是为了将结果集直接输出而设置的,如果在具体使用过程中,为了更友好的显示,可以在这基础上再做加工处理。
  5. errormessage:用来表示出错错误信息,这里包括一条语句中所有的错误信息,用换行符分隔,但有时候如果某一个错误导致不能继续分析了,则后面的错误就不能显示出来。如果没有出错,则用显示为None。而对于执行及备份错误,因为对于一条语句,这样的错误只会有一次,那么执行错误会在后面追加“execute:具体的执行错误原因”,如果是备份出错,则在后面追加“backup:具体的备份错误原因”,而在执行时,有时候会出现Warnings,比如插入数据时字符串被截断啥的,此时会输出这些warnings:#1 Execute(Warning, Code errno):warning message,#号后面的数字表示第几个警告,因为有时候执行一个语句会产生多个警告。
  6. SQL:用来表示当前检查的是哪条sql语句。如果某一条sql语句在检查时有语法错误,则这里面会包括从出错语句开始到后面所有的语句,因为语法出错后实在是真的不能再继续分析了,也就不能将后面的每条语句分开了,这个列还会有一个特别的地方,如果当前语句是inception show xxxx命令集中的第一种情况(<<Inception命令集>>中会做具体介绍)。
  7. affected_rows:用来表示当前语句执行时预计影响的行数,在执行时显示的是真实影响行数。
  8. sequence:这个列与上面说的备份功能有关系,其实就是对应$$Inception_backup_information$$表中的 opid_time 这个列,一一对应,这就为前端应用在针对某一操作回滚找到了入口,每次执行都会产生一个序号,如果要回滚,则就使用这个值从备份表中找到对应的回滚语句执行即可。
  9. backup_dbname:这个列表示的是当前语句产生的备份信息,存储在备份服务器的哪个数据库中,这是一个字符串类型的值,只针对需要备份的语句,数据库名由IP地址、端口、源数据库名组成,由下划线连接,而如果是不需要备份的语句,则返回字符串None。
  10. execute_time:这个列表示当前语句执行时间,单位为秒,精确到小数点后两位。列类型为字符串,使用时可能需要转换成DOUBLE类型的值,如果只是审核而不执行,则这个列返回的值为0。
  11. SQLSHA1:这个列用来存储当前这个语句的一个HASH值,这是用来标识这个语句是不是会使用OSC功能,如果返回信息中有值,则表示这个语句在执行的时候会使用OSC,因为在执行前,会有一次单独的审核操作,此时上层已经可以拿到这个值,审核通过之后,语句是不会改变的,当然这个值也不会改变,那么在执行时就可以使用这个值来查看OSC执行的进度等信息,这个值一般长的样子如下:*D0210DFF35F0BC0A7C95CD98F5BCD4D9B0CA8154,具体其它信息,请参考<<Inception 对OSC的支持>>一章。

友情提示

上面的列,是为了尽可能的丰富的,更灵活的让上层使用,所以列比较多,而如果在具体使用中,如果哪些列觉得没什么意义或者用处不大,可以不关心,特别是只做一个审核页面的话,那么很多列都是不需要关心的,只需要关心ID、errlevel、errormessage、SQL及affected_rows即可。总之一句话,灵活应用即可。当然有任何问题或者疑问都可以随时联系本人(见首页)。

Inception支持选项及意义(5)

在前面<<Inception使用方法>>一章的例子中已经看到部分选项了。我们的选项是通过在SQL语句块前面以注释的方式一起传达给Inception的,它支持的选项还算丰富,这里将详细介绍现在所支持的每个选项的使用方法及意义。


参数名字 是否需要参数 参数是否可选 功能描述
–host 指定将要执行/审核这部分语句块的数据库地址。
–port 指定将要执行这部分语句块的数据库端口。
–password 指定Inception连接数据库的密码。
–user 指定Inception连接数据库的用户名。
–enable-check 告诉Inception当前要做什么操作,是审核还是执行,这个参数与下面的–enable-execute只能指定一个。
–enable-execute 告诉Inception当前要做什么操作,是审核还是执行,这个参数与上面的–enable-check只能指定一个, 如果指定的是这个参数,则Inception在执行前还会做一次实时的审核,那么这个审核和前面指定–enable-check时的审核基本是相同的,因为相同的语句在不同的时间审核产生不同的结果是有可能的(环境有可能变了),所以再做一次审核是有必要的,如果审核发现错误(而不是警告)就不会被执行,当然如果没有指定–enable-ignore-warnings的话,有警告也是不会执行的,但有错误的话,肯定是不会被执行。
–enable-force 告诉Inception,当在执行过程中碰到一个错误时,是中止执行还是保存错误信息继续执行下一个语句,这个参数要谨慎使用。
–enable-ignore-warnings Inception采取严格的分阶段处理,如果审核有问题则不能执行,那么针对一些特殊问题并且审核有警告不通过,但人工审核没问题确定可以执行时,可以选择这个参数,告诉Inception跳过这个警告的检查,继续执行。
–enable-remote-backup 指定在执行时是不是要备份,这个参数默认是打开的,如果不想备份,则指定参数–disable-remote-backup,这个选项所支持的备份,实际上是对当前所执行的操作的备份及被修改数据的回滚语句的存储,关于备份的具体内容,在后面章节中专门介绍。
–enable-split 这个参数是用来拆分要执行的语句块的,如果在语句块中存在对同一个表的DDL操作及DML操作,那么在备份及生成回滚语句分析binlog时,由于表结构已经发生改变,会导致inception没法处理,所以使用这个参数将这些语句分成多批,然后再分别执行,这是在执行前必须要做的一个操作,不然可能产生不可预知的错误,当然在执行前的最后一次审核中,如果检查到有这样的混用情况,会报错返回,而不是警告。这个参数指定之后,除了前面四个参数之外,其它参数都被忽略,也可以不指定。
–enable-query-print 这个参数用来打印提供SQL语句在被MySQL分析之后的执行树结构,以Json的形式提供,目的是为了可以在Inception的基础上,对已经结构化的(Json)被分析之后的语句做再次分析,比如使用到哪些列、语句类型等信息,目前支持的语句类型有:插入、删除、更新及查询,具体详情请参考<<Inception语法树打印>>一节。

现在所支持的选项就上面已经给出的这些,下面是一些特殊说明。
可以看到,上面所说的参数名字除了前面四个连接选项之外,都在前面加了enable,而实际上,这些参数的写法与MySQL配置参数的写法是相同的,比如–enable-check,这个参数的名字只是简单的check,可以写成–check=1,也可以写成–disable-check, 都是比较灵活的,其它的也都是一样的道理。

关于use database,如果没有使用use语句,则必须要在使用表的同时指定库名,即databasename.tablename,否则Inception直接报错,但是如果通过 use 语句指定过一次数据库,当前语句块中,后面可以不再指定,除非想修改当前库的名称,而如果通过databasename.tablename方式指定具体库下面的表,则后面的操作不会受到前面的影响,也就是后面还需要明确指定库名。

Inception使用方法(4)

Inception实际上是一个服务程序,那么它应该有自己的一套友好的使用方式,必须要具备简单、高效、易用等特性。那么为了让Inception具有这些特点,在设计之初,就规定了它的使用方式,如下所述。

通过Inception对语句进行审核时,必须要告诉Inception这些语句对应的数据库地址、数据库端口以及Inception连接数据库时使用的用户名、密码等信息,而不能简单的只是执行一条sql语句,所以必须要通过某种方式将这些信息传达给Inception。而我们选择的方式是,为了不影响语句的意义,将这些必要信息都以注释的方式放在语句最前面,也就是说所有这些信息都是被 /**/括起来的,每一个参数都是通过分号来分隔,类似的方式为:

当然支持的参数不止是这几个,后面还会介绍一些其它的参数。 Inception要做的是一个语句块的审核,需要引入一个规则,将要执行的语句包围起来,Inception规定,在语句的最开始位置,要加上inception_magic_start;语句,在执行语句块的最后加上inception_magic_commit;语句,这2个语句在 Inception 中都是合法的、具有标记性质的可被正确解析的 SQL 语句。被包围起来的所有需要审核或者执行的语句都必须要在每条之后加上分号,其实就是批量执行SQL语句。(包括use database语句之后也要加分号,这点与 MySQL 客户端不同),不然存在语法错误。

在具体执行时,在没有解析到inception_magic_start之前如果发现要执行其它的语句,则直接报错,因为规则中inception_magic_start是强制的。而如果在执行的语句块最后没有出现inception_magic_commit,则直接报错,不会做任何操作。 在前面注释部分,需要指定一些操作的选项,包括线上用户名、密码、数据库地址、检查/执行等,下面是一个简单的例子:


注意:下面说明非常重要,请认真看
那么上面这一段就是一批正常可以执行的SQL语句,目前执行只支持通过C/C++接口、Python接口来对Inception访问,这一段必须是一次性的通过执行接口提交给Inception,那么在处理完成之后,Inception会返回一个结果集,来告诉我们这些语句中存在什么错误,或者是完全正常等等。

请不要将下面的SQL语句块,放到MySQL客户端中执行,因为这是一个自动化运维工具,如果使用交互式的命令行来使用的话没有意义,只能是通过写程序来访问Inception服务器。

而可以通过MySQL客户端来执行的,只有是Inception命令,请参考<<inception命令集语句>>一节。

下面是一段执行上面语句的Python程序的例子:

执行这段程序之后,返回的结果如下:

从返回结果可以看到,每一行语句的审核及执行信息,最前面打印的是field_names,表示Inception的返回结果集的列名信息,总共包括十个列,下面是每个列对应的结果,因为只有两个语句,则只有两行,从结果集第一个列看到只有序号为1和2的两行,而对于每一个列的具体含义,这会在<<Inception结果集>>这一章中讲到,这里只看清楚是什么内容即可。

注意:最后一个“|”后面其实是存储列sqlsha1的,但这里没有改表语句,所以都是空,关于这个信息,请看<<Inception结果集>>一章及<<Inception 对OSC的支持>>一章中相关说明。


需要注意的是,在注释中指定的数据库服务器,必须要有Inception访问它的权限,不然Inception会返回没有访问权限的错误。

Inception安装说明(3)

看到这个手册,想必已经得到了源码,恭喜你。

首先就是编译,在源码根目录下面有一个文件inception_build.sh,执行命令sh inception_build.sh,会输出使用方法。 实际上只需要执行inception_build.sh debug [Xcode]即可,后面的平台是可选的,如果不指定就是linux平台,而如果要指定是Xcode,就后面指定Xcode,而debug是编译的目录,编译之后,所有的生成文件都在这个目录下面,包括可执行文件Inception。可执行文件在debug/sql/Debug/目录下面(不同平台有可能不相同)。

介于在发布之后,很多人使用的是Ubuntu操作系统,这个与其它的有点不同,这里单独说一下在这个下面的编译步骤(其实需要安装的都是编译时所依赖的包,有则略之,无则装之,其它系统仿照这个应该可以轻松搞定):

  1. 下载bison:http://ftp.gnu.org/gnu/bison/,版本最好是2.6之前的,最新的可能会有问题,下载之后,需要自己编译源码来安装,具体安装方法,可以参数网上的一些说明。
  2. cmake安装:apt-get install cmake
  3. ncurses安装:apt-get install libncurses5-dev
  4. 安装openssl:apt-get install libssl-dev
  5. 安装g++:sudo apt-get install g++

安装完成这些,应该是没什么问题了,那么需要注意的是,每次如果出错之后,需要把编译目录删除掉,重新执行,不然会执行出错。

顺便强调说一下,实际上编译Inception,和编译MySQL源码是一样的,如果有不太了解的同学,可以先在网上看看关于MySQL源码的编译,我想遇到的问题都可以解决。

编译完成之后,就是使用了,那么需要一个配置文件(inc.cnf):

上面这些参数的配置都是本人随便举例而已。具体每个参数的意义,请参照后面章节<<Inception所支持的参数变量>>

现在就到启动时间了,那么启动有两种方式,和MySQL是一样的,Inception可执行文件可以在编译目录下面通过find命令找到,编译目录就是在执行inception_build.sh脚本时指定的目录。 1. 所在目录/Inception –defaults-file=inc.cnf
2. 所在目录/Inception –port=6669

第二种方法就是只指定一个端口,其它参数都是默认值,而第一种方法就是在配置文件中可以指定很多参数,按照自己喜欢的规则来配置。

注意: 因为Inception支持OSC执行的功能,是通过调用pt-online-schema-change工具来做的,但如果Inception后台启动(&)的话,可能会导致pt-online-schema-change在执行完成之后,长时间不返回,进而导致Inception卡死的问题,这个问题后面会解决,但现阶段请尽量不要使用后台启动的方式,或者可以使用nohup Inception启动命令 &的方式来启动。

启动如果不报错的话,说明已经启动成功了,实际上很难让它报错,因为非常轻量级

启动成功之后,可以简单试一下看,通过MySQL客户端
mysql -uroot -h127.0.0.1 -P6669
登录上去之后,再执行一个命令:
inception get variables;
输出了所有的变量,恭喜你,已经启动成功了,都说了非常简单。
具体的使用的命令等在后面相应章节都会讲到,继续往后看吧!!!

MysqlFabric 高可用 & 读写分离

感觉有点不够成熟的样子 而且在测试中还存在单点故障 在生产环境谨慎使用

1. 程序必须通过Fabric-aware connectors来连接mysql实现路由,目前只支持PHP,Python 和Java;

2. fabric state store和fabric note当前是单点,虽然fabric-aware连接器可以缓存路由信息(可以配置ttl值);

3. fabric state store(backing store)和fabric note当前是单点,mysqlfabric进程本身不提供容错,出现故障时需要重启,当mysql fabric不可用时,fabric-aware连接器能够通过本地的cache继续路由操作(配置ttl值);– 在测试过程中 backing store挂了 是致命伤(如果能在非常短时间内恢复则没有问题)  即使backint store恢复 也不能正常插入 不知到是脚本问题 还是确实如此

4. mysql实例进行恢复后,fabric不会自动改变实例的状态,需要手工修改;

5. 自动把slaves都设置为read_only 这点值得表扬。

6. 基于GTID的复制本身存在一些限制。

7. 使用fabric不需要对slave配置vip,不像MHA和MMM等需要对vip进行管理;

8. 使用fabric实现mysql复制高可用,以组为单位对mysql实例进行管理,可以管理多个HA组;

9. mysql实例需要指出gtid,也是就要升级到mysql 5.6.10以上版本;

查看mysqlfabric命令帮助:

mysqlfabric help:显示简短的语法信息和帮忙命令

mysqlfabric help commands: 列出所有可用命令和描述

mysqlfabric help groups: 列出可用命令组

mysqlfabric help [group] [command]: 提供命令的详细帮助信息

常用相关命令

mysqlfabricgroup create my_group          #创建HA组

mysqlfabricgroup destroy my_group        #删除HA组

mysqlfabricgroup add my_group 10.1.1.208:3306     #添加组成员

mysqlfabricgroup remove my_group c505ce10-9bc0-11e4-bfd4-000c290e7abe   #移出组成员

mysqlfabricgroup lookup_servers m_ygroup  #查看组成员

mysqlfabricgroup promote my_group –slaves=10.1.1.207:3306     #选举master

mysqlfabric group demote my_group          #降级在组中的任何primary,不会重新选取一个新master,千万不能在业务进行期间做此操作,同时也不会关闭故障检测。

mysqlfabric groupactivate my_group        #激活自动故障转移

mysqlfabric group deactivate my_group           #禁用自动故障转移

mysqlfabric server set_status server_uuid status #变更服务器状态

mysqlfabrichelp manage   #manage命令帮助

mysqlfabrichelp group     #group命令帮助

mysqlfabrichelp server      #server命令帮助

架构图

    10.1.1.206    mysql master
    10.1.1.207    mysql slave
    10.1.1.208    mysql slave
    10.1.1.210    mysqlfabric backingstore(mysql实例) + node(指fabric服务)        — backingstore是一个mysql实例 用于存储管理的mysql实例的角色和状态 版本必须与其他实例的mysql版本一直 而且必须高于5.6.10
fabric

mysql-fabric

配置受管理的mysqld实例 — 206,207,208
— 给所有受管理的mysql实例安装半同步 206,207,208

— Mysql安装好后,每个fabric管理的实例需要开启gtid、二进制日志(不需要启动复制,由fabric完成),将以下配置放到[mysqld]段下面:

添加以下内容

配置Mysql Fabric

    1. — 在backing store节点给fabric node节点授权 必须对fabric库有完全权限 — 在210上操作
    mysql
    2. — 在所有受管理的mysql节点给fabric node节点授权 需要对所有数据库拥有完全权限 — 在206,207,208上操作
    mysql
    3. — 修改fabric配置文件

      修改以下内容

      — 其他参数解释 请查看/mysql/MySQL Utilities/mysqlFabric/fabric.cfg 配置文件详解

    4. — 给backingstore 初始化fabric数据库 — 在210上操作
   # mysqlfabric manage setup –param=storage.user=fabric –param=storage.password=fabric
    ——————————————– 命令执行后的输出————————————–
          [INFO] 1450940601.418141 – MainThread – Initializing persister: user (fabric), server (10.1.1.210:3306), database (fabric).
            Finishing initial setup                                                — 表示完成初始化fabric数据库
            =======================
            Password for admin user is not yet set.
            Password for admin/xmlrpc:                                    — 这里表示要给 admin 设置一个密码 我这里填了fabric
            Repeat Password:                                                       — 再次输入 fabric
            Password set.
            Password set.
            —————————————————————————————————–

运行fabric

    mysqlfabric manage start
    — 如运行上述命令没有提示错误 则使用以下命令把fabric以服务模式运行 日志信息便会输出到日志文件 /var/log/fabric.log
    mysqlfabric manage start –daemonize
    — 关闭命令
    mysqlfabric manage stop                                    — 关闭fabric
    Password for admin:                                             — 输入刚刚初始化fabric数据库时设置的密码 fabric
    — 查看监听端口
    netstat -tnlp | grep python
    tcp        0      0 0.0.0.0:32274               0.0.0.0:*                   LISTEN      30937/python
    tcp        0      0 127.0.0.1:32275             0.0.0.0:*                   LISTEN      30937/python

使用fabric创建mysql复制高可用组

— 创建组 在fabric node 210上操作
mysqlfabric group create my_group                    — 创建组 名称叫my_group
Password for admin:                                                 — 输入admin密码 fabric 也可以把密码写在fabric的配置文件 便不需要每次输入密码 但这里建议每次输入密码 防误操作
—————————————— 创建成功输出 ———————————-
Fabric UUID:  5ca1ab1e-a007-feed-f00d-cab3fe13249e
Time-To-Live: 1
                                uuid finished success result
———————————— ——– ——- ——
12243c47-bd5c-4695-a9f5-29bbeda5618e        1       1      1
state success          when                                                  description
—– ——- ————- ————————————————————
    3       2   1.45094e+09 Triggered by <mysql.fabric.events.Event object at 0xf57c50>.
    4       2   1.45094e+09                            Executing action (_create_group).
    5       2   1.45094e+09                             Executed action (_create_group).
———————————————————————————————-
— 把受管理的mysql实例(206,207,208)添加到组 此操作还不会导致配置主从和failover  在fabric node 210上操作
mysqlfabric group add my_group 10.1.1.206:3306                    — 添加206
Password for admin:                                               — 输入admin密码 fabric
mysqlfabric group add my_group 10.1.1.207:3306                    — 添加207
mysqlfabric group add my_group 10.1.1.208:3306                    — 添加208

查看组信息

 查看状态
mysqlfabric group lookup_servers my_group
———————— 输出如下 —————————————–
Fabric UUID:  5ca1ab1e-a007-feed-f00d-cab3fe13249e
Time-To-Live: 1
                         server_uuid                                         address                    status              mode         weight
————————————                            —————             ———             ———          ——
9507aa71-9280-11e5-88d8-525400ef6331     10.1.1.207:3306     SECONDARY     READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e    10.1.1.208:3306     SECONDARY     READ_ONLY    1.0
f9d3f20e-9ee8-11e5-99c0-525400b3b967      10.1.1.206:3306     SECONDARY     READ_ONLY    1.0
解释
server_uuid                                    — mysql实例的uuid
address                                           — 实例地址
status                                               — 实例状态 primary 表示为主 secondary 表示为从 spare 表示为备用(不能被读写的意思) faulty 表示故障
—————————————————————————–

 查看健康情况

mysqlfabric group health my_group
————————-  输出如下 —————————————–
Fabric UUID:  5ca1ab1e-a007-feed-f00d-cab3fe13249e
Time-To-Live: 1
                                uuid is_alive  status is_not_running is_not_configured io_not_running sql_not_running io_error sql_error
———————————— ——– ——— ————– —————– ————– ————— ——– ———
9507aa71-9280-11e5-88d8-525400ef6331        1     SECONDARY              0                 1              0               0    False     False
e0424b22-9ee9-11e5-99c6-52540082b02e        1     SECONDARY              0                 1              0               0    False     False
f9d3f20e-9ee8-11e5-99c0-525400b3b967        1     SECONDARY              0                 1              0               0    False     False
issue
—–
解释
1为是 0为不是
——————————————————————————

配置主从用户 

— fabric默认用其连接受管理mysql实例的用户配置slave  而且每个slave都有可能成为master 所以要在所有实例上配置 — 在206,207,208上操作
mysql> grant replication slave on *.* to fabric@’10.1.1.206′ identified by ‘fabric’;
mysql> grant replication slave on *.* to fabric@’10.1.1.207′ identified by ‘fabric’;
mysql> grant replication slave on *.* to fabric@’10.1.1.208′ identified by ‘fabric’;
mysql> reset slave;
mysql> reset master;                                — 由于GTIDs的主从是自动position 所以刚刚的授权会在建立主从后 在从再运行一次 这样会导致错误

选出master

— 因为创建高可用组后,fabric没有意识到任何复制拓扑。需要提升一个为primary,降级剩余的服务器自动为secondaries(slaves)。
mysqlfabric group promote my_group –slave_id=10.1.1.206:3306                — 指定10.1.1.206:3306提升为master
——————- 命令解释 ————————————-

# mysqlfabric help group promote

group promote group_id [–slave_id=NONE] [–update_only] [–synchronous]

— 如果只是想更新state store,跳过复制配置,使用–update_only参数。

— 如果slave没有提供,将选择一个最好的候选者,候选者必须开启二进制日志,同时跟master属于同一个组,跟master延时小。进行故障切换操作,选择这个候选者,同时将其他slave指向到新的master,同时更新state store。

— 执行同样的命名将设置不同的服务器为primary,同时降级当前primary并选取一个新的。如果当前primary错误,执行同样的命令能手动触发选取一个新的primary。

—————— 把primary降级——————————–

mysqlfabric group demote my_group

— 使用group demote降级在组中的任何primary,不会重新选取一个新master,千万不能在业务进行期间做此操作,同时也不会关闭故障检测。

——————————————————————–

— 查看提升情况
mysqlfabric group lookup_servers my_group
————————————————- 输出 ———————————————
9507aa71-9280-11e5-88d8-525400ef6331 10.1.1.207:3306 SECONDARY  READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e 10.1.1.208:3306 SECONDARY  READ_ONLY    1.0
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306   PRIMARY READ_WRITE    1.0                        — 状态已变为 PRIMARY 表示主
—————————————————————————————————–
— 查看slave的读写状态 在207 208上操作
show variables like ‘read_only’;
| read_only     | ON    |                                                — fabric 会自动把slave设置为只读 这点非常好
show slave status\G;                                                  — 查看从的情况 没有error则表示成功
— 查看半同步状态
    show status like ‘%semi_sync%’;
    Rpl_semi_sync_master_status                | ON                         — 在206上此值为ON
    Rpl_semi_sync_slave_status                 | ON                            — 在207上此值为ON
    — 表示206和207之间的半同步已成功启用

启用故障检测( failover )

mysqlfabric group activate my_group
    —  mysqlfabric group deactivate my_group           #禁用自动故障转移

模拟故障

— 把master关闭 
mysqladmin -predhat shutdown
— 查看fabricHA组的角色状态
mysqlfabric group lookup_servers my_group
————— 输出如下 ————————————-
                         server_uuid         address    status       mode weight
———————————— ————— ——— ———- ——
9507aa71-9280-11e5-88d8-525400ef6331 10.1.1.207:3306 SECONDARY  READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e 10.1.1.208:3306   PRIMARY READ_WRITE    1.0                    — 自动把208提升为新主
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306    FAULTY READ_WRITE    1.0                        — 关掉的master状态已变为FAULTY
—————————————————————-
— 查看slave 207的情况
show slave status\G;
— master指向新主208 而且没有任何error 则表示切换成功
— 把原master 206恢复
service mysqld start
— 此时虽然原master已经起来 但是fabric并没有把他自动恢复到主从里面 继续下面来验证
— 查看原master恢复后的fabricHA组的角色状态
mysqlfabric group lookup_servers my_group
—————————– 输出如下 ———————————————-
                         server_uuid         address    status       mode weight
———————————— ————— ——— ———- ——
9507aa71-9280-11e5-88d8-525400ef6331 10.1.1.207:3306 SECONDARY  READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e 10.1.1.208:3306   PRIMARY READ_WRITE    1.0
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306    FAULTY READ_WRITE    1.0                    — 原master状态依旧为FAULTY
—————————————————————————————
— 把原master恢复到集群里面
— 一个标记位”faulty”状态的服务器不能提升为secondary或primary,需要先转换成”spare”状态。使用命令mysqlfabric server set_status <server-address> spare
———————相关命令 ———————————————-

# mysqlfabric help server set_status

server set_status server_id status [–update_only] [–synchronous]

Set a server’s status.

支持的状态值为primary,secondary,spare,faulty。

——————————————————————————–

— 切换到spare
mysqlfabric server set_status f9d3f20e-9ee8-11e5-99c0-525400b3b967 spare                        — 把206切换成spare角色,改变到spare,避免写和读访问,同时保证当故障切换时不会被选取。这里需要用206对应的uuid表示 注意要看清楚有没有搞错uuid 当然也可以使用10.1.1.206:3306 这样代替
——————————- mysqlfabric group lookup_servers my_group 查看角色状态 ———————
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306     SPARE    OFFLINE    1.0             — 角色已变为SPARE 而且模式为OFFLINE 表示不会被应用访问到
—————————————————————————————————————————
— 切换到secondary
mysqlfabric server set_status f9d3f20e-9ee8-11e5-99c0-525400b3b967 secondary                — 把206切换成 secondary 角色 成功加入服务
—————– mysqlfabric group lookup_servers my_group 查看角色状态 ———
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306 SECONDARY  READ_ONLY    1.0        — 角色已变为SECONDARY 模式为READ_ONLY
—————————————————————————–

使用python 测试连接数据库和插入数据时故障切换

— 应用程序通过fabric-aware连接器连接到fabric,获取服务器、组信息。

— 创建数据库和表和授权用户 — 在master 206上操作

— 创建库和表
— 给执行python的机器赋予mysqld权限

— 在210上编写脚本 

— 脚本达到无限插入数据并插入失败重新提交

— 执行脚本

模拟故障

— 在脚本执行期间 模拟故障 把master关掉
— 查看组状态

 

— 查看日志文件

——————— 截取日志重点如下————————–

INSERT INTO t1 VALUES (172,”a”)
insert ok                                                                                        — 172插入成功
INSERT INTO t1 VALUES (173,”a”)
Reported faulty server to Fabric (2003: Can’t connect to MySQL server on ‘10.1.1.208:3306’ (111 Connection refused))        — 173插入失败 因为master关掉了
INSERT INTO t1 VALUES (173,”a”)
Reported faulty server to Fabric (2003: Can’t connect to MySQL server on ‘10.1.1.208:3306’ (111 Connection refused))
INSERT INTO t1 VALUES (173,”a”)
Reported faulty server to Fabric (2003: Can’t connect to MySQL server on ‘10.1.1.208:3306’ (111 Connection refused))
INSERT INTO t1 VALUES (173,”a”)
Error getting connection: No MySQL server available for group ‘my_group’ mode=3                                                                    — 可能正在failover 所以获取错误
INSERT INTO t1 VALUES (173,”a”)
insert ok                                                                                                                                                                                                             — 插入成功 仍然插入173 证明没有丢失数据
INSERT INTO t1 VALUES (174,”a”)
insert ok
INSERT INTO t1 VALUES (175,”a”)
——————————————————————–

模拟mysqlfabric故障

— 由于fabric state store和fabric note当前是单点,虽然fabric-aware连接器可以缓存路由信息(可以配置ttl值);

— 模拟backing store 的mysqld故障

— 先把HA组的所有mysqld恢复正常并正常建立主从关系
— 执行脚本
— 把backing store关掉 –210上的mysqld
— 查看日志
————————— 日志输出 ——————————————-
INSERT INTO t1 VALUES (274,”a”)
insert ok                                                                                                        — 把mysqld关掉后一段时间还是能正常插入 估计是TTL时间的设置
INSERT INTO t1 VALUES (275,”a”)
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 104] Connection reset by peer>            — 然后就出错了  而且是即时把mysqld恢复 这里也没有恢复正常
INSERT INTO t1 VALUES (275,”a”)
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 104] Connection reset by peer>
————————————————————————————
— 但把python脚本关掉 重新跑 又可以了 其中的原因 暂时还不得知

— 模拟fabric node( fabric进程 )故障

— 先把HA组的所有mysqld恢复正常并正常建立主从关系
— 执行脚本

— 把fabric关掉

— 查看日志

————————— 日志输出 ———————————————–
INSERT INTO t1 VALUES (270,”a”)
insert ok                                                                                                        — 也是能正常插入一段时间
INSERT INTO t1 VALUES (271,”a”)
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 111] Connection refused>            — 然后就报错了 因为把fabric进程关了
INSERT INTO t1 VALUES (271,”a”)
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 111] Connection refused>
INSERT INTO t1 VALUES (271,”a”)
insert ok
— 把fabric重新启动之后 插入又正常了
————————————————————————————–
测试总结:
— 在测试过程中 backing store挂了 是致命伤(如果能在非常短时间内恢复则没有问题)  即使backint store恢复 也不能正常插入 不知到是脚本问题 还是确实如此
— fabric进程挂了 在进程恢复后 就能恢复正常
— 在backing store挂的期间 如果master也挂了 fabric也能正常处理failover
— 在fabric进程挂了期间 (他压根不工作好吧 还怎么failover呢)
— 调大TTL值

 

— 重新测试上面2个单点故障

— 结果一模一样 压根不是调大TTL值就能解决的 致命伤啊

组维护

1、找出哪些服务器在组中,查看组状态

2、从组中移除mysql实例

— 有时需要将secondaries离线进行维护,在停止服务之前,需要先从组中移除它,避免fabric错误检查触发任何动作:

— 如从my_group组中移除server_uuid为7bd52611-2d44-11e4-af5f-3ecad7c2f82a的实例:

— 然后可以重新添加到组,将自动开启复制:

3、添加一个全新的Mysql实例(实例IP为172.17.0.51)到HA group组

— 查看前面的创建过程即可

4、降级primary

— primary不能从组中移除,使用group demote关闭在组中的任何primary,不会重新选取一个新master,同时也不会关闭故障检测。

 

5、手动提升一个服务组,选取一个master

6、移除组(使用group destroy)

— 如果组没有服务器,是空的,能移除组

— 也能强制的移除非空的组(使用–force):