Archive for the ‘mysql’ Category.

mysql show slave status

 



1. 概览

  mysql的replication复制可以通过show slave status;
  我们天天都在用,但是对它的理解却不见的很深,
  特别把show slave status的每一项都解析一下
  如下是一个普通的MySQL show slave status的输出:
  admin@localhost : (none) 05:59:24> show slave status\G
  *************************** 1. row ***************************
                 Slave_IO_State: Waiting for master to send event
                    Master_Host: 172.20.164.67
                    Master_User: repl
                    Master_Port: 3306
                  Connect_Retry: 60
                Master_Log_File: mysql-bin.001896
            Read_Master_Log_Pos: 226029100
                 Relay_Log_File: mysql-relay-bin.002014
                  Relay_Log_Pos: 87341525
          Relay_Master_Log_File: mysql-bin.001896
               Slave_IO_Running: Yes
              Slave_SQL_Running: Yes
                Replicate_Do_DB:
            Replicate_Ignore_DB:
             Replicate_Do_Table:
         Replicate_Ignore_Table:
        Replicate_Wild_Do_Table:
    Replicate_Wild_Ignore_Table:
                     Last_Errno: 0
                     Last_Error:
                   Skip_Counter: 0
            Exec_Master_Log_Pos: 226029100
                Relay_Log_Space: 87341723
                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: 0
  Master_SSL_Verify_Server_Cert: No
                  Last_IO_Errno: 0
                  Last_IO_Error:
                 Last_SQL_Errno: 0
Last_SQL_Error:

做了一个列表,简单注释了一下各个字段的意思,如下:

字段名 注释 可能取值 取值示例
Slave_IO_State slave状态的文字描述 slave线程状态 Waiting for master to send event
Master_Host master的IP或主机名 172.20.164.67
Master_User 连接master使用的用户名 repl
Master_Port 连接master使用的密码 3306
Connect_Retry 重新连接MySQL的重试间隔时间,单位秒 60
Master_Log_File IO thread读取到的binlog日志文件 Master_Log_File,Read_Master_Log_Pos;Relay_Log_File,Relay_Log_Pos;Relay_Master_Log_File,Exec_Master_Log_Pos的具体位置 mysql-bin.001896
Read_Master_Log_Pos IO thread读取到的binlog日志文件位置 226029100
Relay_Log_File slave 在本地缓存的relay 日志的文件名 mysql-relay-bin.002014
Relay_Log_Pos slave 在本地缓存的relay 日志的文件位置 87341525
Relay_Master_Log_File SQL thread 执行到master的binlog文件名 mysql-bin.001896
Slave_IO_Running IO thread是否正常运行 Yes
Slave_SQL_Running SQL thread是否正常运行 Yes
Replicate_Do_DB slave上需要执行的schema
Replicate_Ignore_DB slave上需要忽略的schema
Replicate_Do_Table slave上需要执行的table
Replicate_Ignore_Table slave上需要忽略的table
Replicate_Wild_Do_Table slave上需要执行的table正则表达式
Replicate_Wild_Ignore_Table slave上需要忽略的table正则表达式
Last_Errno 上一次出错的错误号 0
Last_Error 上一次出错的错误信息
Skip_Counter 还剩下的忽略event次数 0
Exec_Master_Log_Pos SQL thread 执行到master的binlog文件位置 226029100
Relay_Log_Space relay log占用的空间大小 87341723
Until_Condition 复制until条件,在stop slave,start slave(不带until)或server重启的时候会自动重置 None
Until_Log_File 复制停止的文件名
Until_Log_Pos 复制停止的文件位置 0
Master_SSL_Allowed 是否使用SSL连接master No
Master_SSL_CA_File ssl agent文件ca-cert.pem的文件名 /etc/mysql/newcerts/ca-cert.pem
Master_SSL_CA_Path ssl agent文件ca-cert.pem的路径名
Master_SSL_Cert ssl 授权文件 /etc/mysql/newcerts/client-cert.pem
Master_SSL_Cipher ssl 加密算法
Master_SSL_Key ssl 密钥文件 /etc/mysql/newcerts/client-key.pem
Seconds_Behind_Master SQL thread相对master的延迟时间 0
Master_SSL_Verify_Server_Cert 是否检查master的授权文件 No
Last_IO_Errno IO thread的上一次出错的错误号 0
Last_IO_Error IO thread的上一次出错的错误信息
Last_SQL_Errno SQL thread的上一次出错的错误号 0
Last_SQL_Error SQL thread的上一次出错的错误信息
  这么多信息,有一些是一看就知道是什么意思的字段。
  其他的至少可以分为以下几个专题:
  • IO thread, SQL thread状态变更
  • Master_Log_File,Read_Master_Log_Pos;Relay_Log_File,Relay_Log_Pos;Relay_Master_Log_File,Exec_Master_Log_Pos的具体位置
  • Replicate_Do, Replicate_Ignore 讨论
  • mysql ssl连接
  • replication文件 master.info, relay.info和连接信息解析
  • Seconds_Behind_Master 精确性
  • replication until和复制延迟控制
  • skip counter忽略event计数和精确性本文只涉及第一和第二个议题

2. IO thread, SQL thread状态变更

  1. IO线程状态变更,对应show slave status的Slave_IO_State字段
名称 状态值 解释
wait_master Waiting for master update
connect_master Connecting to master
check_master Checking master version
register_slave Registering slave on master
request_binlog Requesting binlog dump
request_wait_reconnect Waiting to reconnect after a failed binlog dump request
request_reconnecting Reconnecting after a failed binlog dump request
wait_event Waiting for master to send event
queue_to_relay_log Queueing master event to the relay log
read_wait_reconnect Waiting to reconnect after a failed master event read
read_reconnecting Reconnecting after a failed master event read
wait_relay_space Waiting for the slave SQL thread to free enough relay log space
wait_slave_mutex Waiting for slave mutex on exit

状态变更图如下:
io_thread 状态变更
代码请参考sql/slave.cc的handle_slave_io函数

  1. SQL线程状态变更,对应服务器上SQL线程的State字段,通过show processlist查看
名称 状态值 解释
wait_relay_event Waiting for the next event in relay log
read_relay Reading event from the relay log
wait_io_thread Has read all relay log; waiting for the slave I/O thread to update it
make_temp_file Making temp file
wait_slave_mutex Waiting for slave mutex on exit

状态变更图如下:

sql_thread 状态变更

代码请参考sql/slave.cc的handle_slave_sql函数

3. Master_Log_File,Read_Master_Log_Pos;Relay_Log_File,Relay_Log_Pos;Relay_Master_Log_File,Exec_Master_Log_Pos的具体位置

  1. 定义
  • Master_Log_File,Read_Master_Log_Pos 记录了IO thread读到的当前master binlog文件和位置,对应master的binlog文件和位置。
  • Relay_Log_File,Relay_Log_Pos记录了SQL thread执行到relay log的那个文件和位置,对应的是slave上的relay log文件和位置。
  • Relay_Master_Log_File,Exec_Master_Log_Pos记录的是SQL thread执行到master binlog的文件和位置,对应的master上binlog的文件和位置。
  1. 日志文件介绍需要明确这几个值的意思,我们首先需要了解binlog日志文件和relay log日志文件的具体结构。binlog的文件格式可以参考 Mats Kindah和Lars Thalman的binlog API文档。binlog的event可以参考我之前的blog和binlog events 介绍
    • binlog数据文件示例binlog文件和relay log文件都可以用mysqlbinlg工具来打开。下图是一个mysqlbinlog解析普通的binlog文件出来的文本文件:我们这里主要是row方式的binlog。

      注意:binlog的event语句开始位置就是二进制binlog文件的字节偏移位置。而且根据上一个event的end_log_pos可以找到下一个event开始的位置,如上图所示。

  • relay log数据文件示例binlog文件和relay log文件都可以用mysqlbinlg工具来打开。下图是一个mysqlbinlog解析普通的relay log文件出来的文本文件:relay log和binlog记录方式基本相同,最大的不同就是end_log_pos记录的是master的binlog文件中event的位置,而不是relay log自己event的位置。如图所示,上一个event的end_log_pos和下一个relay log event开始的位置不一样。

为什么需要这样设置?原因很简单,就是为了方便找到master binlog的位置,在slave上,记录relay log 下一个event的开始偏移意义不大,但是如果记录了master binlog的偏移量,我们就可以在SQL thread中明确我们执行到master的某个binlog的哪个位置了。那么是哪个binlog列。我们找到relay log的最前面。

如图所示,每个relay log开头都有这么一个rotate event,也就是当前master的binlog文件名。引用一下Automated master failover的一页PPT如下。

这里列出了Read_Master_Log_Pos,Relay_Log_Pos,Exec_Master_Log_Pos 的具体位置。

  • IO thread 把所有从master读到的binlog记录到本地的binlog中,所以relay log的最后一个event的end log_pos就是Read_Master_Log_Pos
  • SQL thread 按照transaction来执行,所以Exec_Master_Log_Pos对应relay log中最后一个事务event的end_log_pos,这个位置对应的是master的binlog的位置。
  • Relay_Log_Pos 记录的是SQL thread执行的event在relay log中结束位置,这个才是relay log的偏移量。

4. 参考资料

mysql reference IO 线程状态

mysql reference SQL 线程状态

mysql reference show slave status

binlog events

binlog API

Automated master failover


做加法的shell函数

写了一个对所有传入的参数做加法的shell函数,贴上来,给大家参考。

没有做什么异常处理,利用bc来计算

function calc_sum()
{
    if [ $# -lt 1 ]; then
        echo 0
        return 0
    fi

    local __SUM_STR="scale=2;"
    local __VAR_COUNT=$#
    for i in `seq 1 $#`; do
        __SUM_STR="$__SUM_STR \$$i +"
    done

    #### cut the last  +
    __SUM_STR=${__SUM_STR%+*}

    #### cal the sum
    eval echo "\"$__SUM_STR\"" | bc
}

percona参数设置标准

percona参数设置

  1. 首先为参数设置中的对应符号,函数设置
符号,函数 解释
ceil() 向上取整
HTC CPU超线程数(HyperThread Count)
IC 一个主机上的MySQL实例个数(Instance Count)
IC 一个主机上的MySQL实例个数(Instance Count)
PDC mydata所在的逻辑盘对应的物理盘个数(Physical Disk Count)
ERSV innodb_extra_rsegments值大小(innodb_Extra_RSegments Value)
NULL 对应的参数不设置在my.cnf,也就是说使用该参数的默认值
  1. 在my.cnf中可以设置的参数如下
      # innodb plugin
      innodb_read_io_threads=1
      innodb_write_io_threads=4
      innodb_io_capacity=10000
      innodb_file_format=barracuda
      innodb_file_format_check=ON
      innodb_strict_mode=1
    
    innodb_adaptive_flushing=false
      # percona
      innodb_page_size=8k
      innodb_extra_rsegments=8
      innodb_use_purge_thread=4
      innodb_stats_update_need_lock=0
      innodb_fast_checksum=1
      log_slow_verbosity=full
      userstat_running=1
      enable_query_response_time_stats=1
      # percona For SSD
      #innodb_adaptive_checkpoint=3
      innodb_flush_neighbor_pages=0
    
参数名 SAS (默认为Raid 1+0) 应该设置值 SSD (默认为Raid 5) 应该设置值 Fusion io (采用flashcache) 应该设置值 备注
innodb_read_io_threads 1 1 1 预读线程只需要设置为1
innodb_write_io_threads ceil(HTC / IC) ceil(HTC / IC) ceil(HTC / IC) 写线程设置为线程数除以实例个数
innodb_io_capacity ceil((PDC * 200 ) / IC ) ceil(((PDC – 1) * 2000 ) / IC ) ceil(40000 / IC) io_capacity主要跟机器的IO性能有关。SAS一块盘写能力假设为200,SSD一块盘假设为2000,fusion io假设为40000。
innodb_file_format barracuda barracuda barracuda percona默认文件格式为barracuda
innodb_file_format_check ON ON ON MySQL使用barracuda需要在启动的时候检查文件格式为innodb_file_format
innodb_strict_mode=1 1 1 1 严格检查文件格式,如果有文件格式高于innodb_file_format,实例不能启动
innodb_page_size=8k 8k 8k 8k MySQL文件页大小默认使用8k
innodb_extra_rsegments=8 ceil(HTC / IC) ceil(HTC / IC) ceil(HTC / IC) 额外的回滚段个数设置为CPU超线程数除以MySQL实例个数
innodb_use_purge_thread=4 ceil(ERSV / 2) ceil(ERSV / 2) ceil(ERSV / 2) purge线程数设置为额外的回滚段个数的一半
innodb_stats_update_need_lock=0 0 0 0 取消更新状态信息时的锁操作
innodb_fast_checksum=1 1 1 1 使用percona的更快的checksum算法,其实是不计算checksum
log_slow_verbosity=full full full full 详细记录慢查
userstat_running=1 1 1 1 记录用户统计信息
enable_query_response_time_stats=1 1 1 1 记录SQL响应时间信息
innodb_adaptive_checkpoint=3 NULL if(IC>4) then NULL; else 3; if(IC>4) then NULL; else 3; SAS盘不设置该参数;SSD和fusion io的如果MySQL实例在4个已上,担心0.1秒的flush频率太高对主机影响太大,不设置,采用默认值,如果实例数在4个或者4个以下,设置为3。
innodb_flush_neighbor_pages=0 NULL 0 0 对随机写不敏感的SSD和fusion io设置为不刷写邻居页,对SAS不设置,采用默认值
innodb_adaptive_flushing=false false false false 不使用innodb的自适应刷新算法


mysql事件类型和文件头长度

附录

附录1 MySQL 5.1.20 Beta包含的事件类型

下面列举了各种MySQL的事件类型(代码拷贝自MySQL 5.1.20的源代码):

enum Log_event_type

{

/*

Every time you update this enum (when you add a type), you have to

fix Format_description_log_event::Format_description_log_event().

*/

UNKNOWN_EVENT= 0,

START_EVENT_V3= 1,

QUERY_EVENT= 2,

STOP_EVENT= 3,

ROTATE_EVENT= 4,

INTVAR_EVENT= 5,

LOAD_EVENT= 6,

SLAVE_EVENT= 7,

CREATE_FILE_EVENT= 8,

APPEND_BLOCK_EVENT= 9,

EXEC_LOAD_EVENT= 10,

DELETE_FILE_EVENT= 11,

/*

NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer

sql_ex, allowing multibyte TERMINATED BY etc; both types share the

same class (Load_log_event)

*/

NEW_LOAD_EVENT= 12,

RAND_EVENT= 13,

USER_VAR_EVENT= 14,

FORMAT_DESCRIPTION_EVENT= 15,

XID_EVENT= 16,

BEGIN_LOAD_QUERY_EVENT= 17,

EXECUTE_LOAD_QUERY_EVENT= 18,

TABLE_MAP_EVENT = 19,

/*

These event numbers were used for 5.1.0 to 5.1.15 and are

therefore obsolete.

*/

PRE_GA_WRITE_ROWS_EVENT = 20,

PRE_GA_UPDATE_ROWS_EVENT = 21,

PRE_GA_DELETE_ROWS_EVENT = 22,

/*

These event numbers are used from 5.1.16 and forward

*/

WRITE_ROWS_EVENT = 23,

UPDATE_ROWS_EVENT = 24,

DELETE_ROWS_EVENT = 25,

/*

Something out of the ordinary happened on the master

*/

INCIDENT_EVENT= 26,

/*

Add new events here – right above this comment!

Existing events (except ENUM_END_EVENT) should never change their numbers

*/

ENUM_END_EVENT /* end marker */

};

附录2 MySQL 5.1.20 Beta各事件的附加事件头长度

下面列举了MySQL 5.1.20 Beta各事件的附加事件头长度(拷贝自MySQL源代码):

/* event-specific post-header sizes */

// where 3.23, 4.x and 5.0 agree

#define QUERY_HEADER_MINIMAL_LEN (4 + 4 + 1 + 2)

// where 5.0 differs: 2 for len of N-bytes vars.

#define QUERY_HEADER_LEN (QUERY_HEADER_MINIMAL_LEN + 2)

#define LOAD_HEADER_LEN (4 + 4 + 4 + 1 +1 + 4)

#define START_V3_HEADER_LEN (2 + ST_SERVER_VER_LEN + 4)

#define ROTATE_HEADER_LEN 8 // this is FROZEN (the Rotate post-header is frozen)

#define CREATE_FILE_HEADER_LEN 4

#define APPEND_BLOCK_HEADER_LEN 4

#define EXEC_LOAD_HEADER_LEN 4

#define DELETE_FILE_HEADER_LEN 4

#define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES)

#define ROWS_HEADER_LEN 8

#define TABLE_MAP_HEADER_LEN 8

#define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1)

#define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)

#define INCIDENT_HEADER_LEN 2

post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;

post_header_len[QUERY_EVENT-1]= QUERY_HEADER_LEN;

post_header_len[ROTATE_EVENT-1]= ROTATE_HEADER_LEN;

post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN;

post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN;

post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN;

post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN;

post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN;

post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1];

post_header_len[FORMAT_DESCRIPTION_EVENT-1]= FORMAT_DESCRIPTION_HEADER_LEN;

post_header_len[TABLE_MAP_EVENT-1]= TABLE_MAP_HEADER_LEN;

post_header_len[WRITE_ROWS_EVENT-1]= ROWS_HEADER_LEN;

post_header_len[UPDATE_ROWS_EVENT-1]= ROWS_HEADER_LEN;

post_header_len[DELETE_ROWS_EVENT-1]= ROWS_HEADER_LEN;

/*

We here have the possibility to simulate a master of before we changed

the table map id to be stored in 6 bytes: when it was stored in 4

bytes (=> post_header_len was 6). This is used to test backward

compatibility.

This code can be removed after a few months (today is Dec 21st 2005),

when we know that the 4-byte masters are not deployed anymore (check

with Tomas Ulin first!), and the accompanying test (rpl_row_4_bytes)

too.

*/

DBUG_EXECUTE_IF(“old_row_based_repl_4_byte_map_id_master”,

post_header_len[TABLE_MAP_EVENT-1]=

post_header_len[WRITE_ROWS_EVENT-1]=

post_header_len[UPDATE_ROWS_EVENT-1]=

post_header_len[DELETE_ROWS_EVENT-1]= 6;);

post_header_len[BEGIN_LOAD_QUERY_EVENT-1]= post_header_len[APPEND_BLOCK_EVENT-1];

post_header_len[EXECUTE_LOAD_QUERY_EVENT-1]= EXECUTE_LOAD_QUERY_HEADER_LEN;

post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN;

附录3 MySQL 5.1.20 Beta中各列在内部存储时可能的各种数据类型

enum enum_field_types

{

MYSQL_TYPE_DECIMAL = 0,

MYSQL_TYPE_TINY = 1,

MYSQL_TYPE_SHORT = 2,

MYSQL_TYPE_LONG = 3,

MYSQL_TYPE_FLOAT = 4,

MYSQL_TYPE_DOUBLE = 5,

MYSQL_TYPE_NULL = 6,

MYSQL_TYPE_TIMESTAMP = 7, // 4 from_unixtime(0x)

MYSQL_TYPE_LONGLONG = 8,

MYSQL_TYPE_INT24 = 9, //field_medium

MYSQL_TYPE_DATE = 10,

MYSQL_TYPE_TIME = 11,

MYSQL_TYPE_DATETIME = 12,

MYSQL_TYPE_YEAR = 13,

MYSQL_TYPE_NEWDATE = 14,

MYSQL_TYPE_VARCHAR = 15, //field_varstring

MYSQL_TYPE_BIT = 16,

MYSQL_TYPE_NEWDECIMAL = 246,

MYSQL_TYPE_ENUM = 247,

MYSQL_TYPE_SET = 248,

MYSQL_TYPE_TINY_BLOB = 249,

MYSQL_TYPE_MEDIUM_BLOB = 250,

MYSQL_TYPE_LONG_BLOB = 251,

MYSQL_TYPE_BLOB = 252,

MYSQL_TYPE_VAR_STRING = 253,

MYSQL_TYPE_STRING = 254,

MYSQL_TYPE_GEOMETRY = 255,

};

附录4 MySQL 5.1.20 Beta中各ROW_EVENTm_flags包含的标志位

MySQL 5.1.20 Beta中,各ROW_EVENT都含有m_flags标志位集合。可能的标志如下:

名称

含义

STMT_END_F

1

语句执行结束标志

NO_FOREIGN_KEY_CHECKS_F

2

不进行外键约束检查的标志

RELAXED_UNIQUE_CHECKS_F

4

不进行唯一键约束检查的标志

相关代码如下:

/*

These definitions allow you to combine the flags into an

appropriate flag set using the normal bitwise operators. The

implicit conversion from an enum-constant to an integer is

accepted by the compiler, which is then used to set the real set

of flags.

*/

enum enum_flag

{

/* Last event of a statement */

STMT_END_F = (1U << 0),

/* Value of the OPTION_NO_FOREIGN_KEY_CHECKS flag in thd->options */

NO_FOREIGN_KEY_CHECKS_F = (1U << 1),

/* Value of the OPTION_RELAXED_UNIQUE_CHECKS flag in thd->options */

RELAXED_UNIQUE_CHECKS_F = (1U << 2)

};

typedef uint16 flag_set;

/* Special constants representing sets of flags */

enum

{

RLE_NO_FLAGS = 0U

};

mysql replication数据复制格式



















1.1MySQL
replication
数据复制格式



这里我们基于MySQL
5.1.20
Beta
描述MySQL两个slave端的thread发送和接收数据的格式。某些字段所占的字节数跟MySQL的版本有关,这里我们所描述的为binlog版本为4MySQL
server
版本为5.1.20
Beta
下的数据格式。


1.1.1MySQL
I/O thread
数据格式


1.1.1.1向主服务器注册自己



向主服务器注册自己并不是一个必须的操作,如果没有注册同样可以向主服务器请求数据。如果需要向主服务器注册,那么可以调用mysql.h中的simple_command(mysql,
command, arg, length,
skip_check)
函数,在arg参数中依序填入下述的各个字段,并指定其中的参数commandCOM_REGISTER_SLAVE以注册自己。



































































名称




字节数




含义




server_id




4




MySQL
instance
server_id




strlen(report_host)




1 or
2




标识接下来的report_host的长度,如果长度<2511个字节,否则占两个字节




report_host




Strlen(report_host)




向主服务器注册的MySQL
instance
标识




strlen(report_user)




1 or
2




标识接下来的report_user的长度,如果长度<2511个字节,否则占2个字节




report_user




Strlen(report_user)




向主服务器注册的用户名




strlen(report_password)




1 or
2




标识接下来的report_password的长度,如果长度<2511个字节,否则占2个字节




report_password




Strlen(report_password)




向主服务器注册的密码




report_port




2




向主服务器注册的端口




rpl_recovery_rank




4




复制的恢复等级




master_id




4




填入0,主服务器将自行填入master_id




1、主服务器注册示意图







1.1.1.2向主服务器请求数据



从服务器向主服务器发送了请求数据的命令以后主服务器将根据要求将对应binlog文件的指定位置开始的事件记录发送给从服务器。向主服务器请求数据,可以调用mysql.h中的simple_command(mysql,
command, arg, length,
skip_check)
函数,在arg参数中依序填入下述的各个字段,并指定其中的参数commandCOM_BINLOG_DUMP





































名称




字节数




含义




master_log_pos




4




请求主服务器发送的事件记录在binlog文件中的偏移量




binlog_flags




2




暂时填0,做扩展用




server_id




4




MySQL
instance
server_id




logname




Strlen(logname)




请求主服务器发送的binlog文件的文件名




如果没有指定MySQL使用methods,那么我们应该调用函数sql_common.h头文件中的cli_advanced_command()代替simple_command()。



向主服务器请求了数据以后,从服务器就可以通过cli_safe_read(mysql);获得主服务器发送过来的数据,每次获得一个事件记录的数据。cli_safe_read的返回值标示了从主服务器发送过来的数据的数据字节数。而发送过来的数据保存在mysql->net->read_pos数组中。I/O
thread
模块可以利用MySQLio_cache将对应事件记录存储到relay-log文件中。






1.1.1.3MySQL
binlog
文件初始化



由于MySQL
binlog
的特殊性,以及为了mysqlbinlog工具能够识别我们relay-log文件,在新建一个relay-log文件时必须写入一定的初始化数据。这些初始化数据依序包括如下字段:


















名称




字节数




含义




BINLOG_MAGIC("\xfe\x62\x69\x6e")




BIN_LOG_HEADER_SIZE(4)




Binlog文件的标识值







1.1.2MySQL
SQL thread
数据格式



只要循环的调用cli_safe_read函数,从服务器可以不断得到从主服务器发送过来的事件记录。接下来我们介绍一下相关的一些事件记录格式。在提交了COM_BINLOG_DUMP命令后,主服务器首先给从服务器发送的两个事件依序分别为ROTATE_EVENTFORMAT_DESCRIPTION_EVENT事件。ROTATE_EVENT事件用来标示接下来主服务器将从哪一个binlog文件的哪个位置开始发送事件记录。而FORMAT_DESCRIPTION_EVENT事件用来记录本MySQL
instance
server_id值,binlog版本号,MySQL
server
的版本,本relay-log创建的时间以及各个不同事件的事件头所占的字节数等信息。我们关心的其他的事件记录的格式包括WRITE_ROWS_EVENTUPDATE_ROWS_EVENTDELETE_ROWS_EVENT等。






1.1.2.1事件头字段描述



各个事件都包括一个事件头,事件头的字段格式如下:











































名称




字节数




含义




When




4




事件的创建时间。




Type




1




事件的类型(见附录1)




server_id




4




事件发生时所在MySQLserver_id值。




data_written




4




该事件一共占用的字节数,包括事件头的字节数。




log_pos




4




下一事件在binlog文件中将要开始的位置,即本事件的结束位置




Flags




2




事件的其他标志位。







1.1.2.2ROTATE_EVENT事件字段描述



由于各个事件的事件头基本一致,这里我们就不重复介绍事件头的各字段了,后面的各个事件我们也都将忽略对事件头字段的描述。



ROTATE_EVENT事件的附加事件头字段主要包括:


















名称




字节数




含义




pos




8




主服务器将要发送的事件记录在binlog文件中的偏移量。一般为从服务器提交的COM_BINLOG_DUMP请求中的偏移量值。




ROTATE_EVENT事件的其他信息字段主要包括:


















名称




字节数




含义




new_log_ident




strlen(new_log_ident)




主服务器将要发送的事件记录的binlog文件名。一般为从服务器提交的COM_BINLOG_DUMP请求中的binlog文件名。







1.1.2.3FORMAT_DESCRIPTION_EVENT事件字段描述



FORMAT_DESCRIPTION_EVENT事件的附加事件头的字段如下:






































名称




字节数




含义




binlog_version




2




Binlog文件的版本号,这里一般为最新的版本号4




server_version




ST_SERVER_VER_LEN(50)




MySQL的版本号。例如:”
5.1.20-beta-log”




Created




4




事件创建时间,这里一般和事件头中的when一致




event_header_len




1




一般事件的事件头长度,一般设置为:LOG_EVENT_HEADER_LEN(19)




post_header_len




ENUM_END_EVENT-1(26)




不同事件类型的附加事件头的长度,见附录2








1.1.2.4TABLE_MAP_EVENT事件字段描述



TABLE_MAP_EVENT事件的附加事件头的字段如下:























名称




字节数




含义




m_table_id




6(5.1.4前的版本中为4)




表的id标识符




m_flags




2




表的各种标志位,见附录4




TABLE_MAP_EVENT事件的其他信息字段主要包括:











































名称




字节数




含义




m_dblen




1




数据库名的长度




m_dbnam




m_dblen+1




数据库名,以’\0’结尾




m_tbllen




1




表名的长度




m_tblnam




m_tbllen+1




表名,以’\0’结尾




m_colcnt




net_field_length()




表的字段个数,所占字节数根据第一个字节的大小由net_field_length函数确定




m_coltype




m_colcnt




表的各个字段的字段类型,参见附录3








1.1.2.5WRITE_ROWS_EVENT事件字段描述



WRITE_ROWS_EVENT事件的附加事件头的字段如下:























名称




字节数




含义




m_table_id




6(5.1.4前的版本中为4)




表的id标识符




m_flags




2




表的各种标志位,见附录4




WRITE_ROWS_EVENT事件的其他信息字段主要包括:




























名称




字节数




含义




m_width




net_field_length()




表的各列的位图长度,所占字节数根据第一个字节的大小由net_field_length函数确定




m_cols.bitmap




(m_width
+ 7) / 8




表的各列的位图,每一位表示m_rows_buf是否包含表中一列的值,如果没有置位表示该列的值没有包含在m_rows_buf




m_rows_buf




剩余字节数(len-已占字节数)




将要插入到表中的一行数据值。







1.1.2.6UPDATE_ROWS_EVENT事件字段描述



UPDATE_ROWS_EVENT事件的附加事件头的字段如下:























名称




字节数




含义




m_table_id




6(5.1.4前的版本中为4)




表的id标识符




m_flags




2




表的各种标志位,见附录4




UPDATE_ROWS_EVENT事件的其他信息字段主要包括:

































名称




字节数




含义




m_width




net_field_length()




表的各列的位图长度,所占字节数根据第一个字节的大小由net_field_length函数确定




m_cols.bitmap




(m_width
+ 7) / 8




表中被匹配行数据的各列的位图,每一位表示m_rows_buf是否包含表中该列的值。




m_cols_ai.bitmap




(m_width
+ 7) / 8




表中将要更新的行数据的各列的位图,每一位表示m_rows_buf是否包含表中一列的值。




m_rows_buf




剩余字节数(len-已占字节数)




表中被匹配的那一行数据的值以及将要更新的一行数据值。








1.1.2.7DELETE_ROWS_EVENT事件字段描述



DELETE_ROWS_EVENT事件的附加事件头的字段如下:























名称




字节数




含义




m_table_id




6(5.1.4前的版本中为4)




表的id标识符




m_flags




2




表的各种标志位




DELETE
_ROWS_EVENT
事件的其他信息字段主要包括:




























名称




字节数




含义




m_width




net_field_length()




表的各列的位图长度,所占字节数根据第一个字节的大小由net_field_length函数确定




m_cols.bitmap




(m_width
+ 7) / 8




表的各列的位图,每一位表示m_rows_buf是否包含表中一列的值。




m_rows_buf




剩余字节数(len-已占字节数)




表中将要删除的一行数据值。







1.1.2.8XID_EVENT事件字段描述



XID_EVENT一般出现在一个事务操作(transaction)之后或者其他语句提交之后。它的主要作用是提交事务操作和把事件刷新至binlog文件中。



XID_EVENT事件的信息字段包括:


















名称




字节数




含义




xid




sizeof(xid)
8




commit标识符











5




MySQL 5.1的新特性

把08年左右自己写的东西翻出来凑个数,主要是翻译的MySQL reference相关章节

MySQL 5.1的新特性
MySQL在版本5.1中增加了很多新特性,其中的row based replication是mmrd要求必须满足的条件。目前为止,也许是出于谨慎或者稳定性的目的,MySQL 5.1虽然已经出到版本5.1.26了,仍然是Release Candidate Development Release,不能用于生产环境。不过SUN和MySQL公司还是声称将于近期推出可供生产环境使用的Release版本。下面我们列出主要的MySQL的主要新特性并进行简单介绍。

Partitioning分区
数据库分区是一种物理数据库设计技术,虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。分区主要有两种形式:(这里一定要注意行和列的概念(row是行,column是列))
水平分区(Horizontal Partitioning):这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。举个简单例子:一个包含十年发票记录的表可以被分区为十个不同的分区,每个分区包含的是其中一年的记录。
垂直分区(Vertical Partitioning):这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。
在数据库供应商开始在他们的数据库引擎中建立分区(主要是水平分区)时,DBA和建模者必须设计好表的物理分区结构,不要保存冗余的数据(不同表中同时都包含父表中的数据)或相互联结成一个逻辑父对象(通常是视图)。这种做法会使水平分区的大部分功能失效,有时候也会对垂直分区产生影响。
分区带来的好处有很多,这里列出两点:
性能的提升(Increased performance):在扫描操作中,如果MySQL的优化器知道哪个分区中才包含特定查询中需要的数据,它就能直接去扫描那些分区的数据,而不用浪费很多时间扫描不需要的地方 了。需要举个例子,百万行的表划分为10个分区,每个分区就包含十万行数据,那么查询分区需要的时间仅仅是全表扫描的十分之一了,很明显的对比。同时对十万行的表建立索引的速度也会比百万行的快得多得多。如果你能把这些分区建立在不同的磁盘上,这时候的I/O读写速度就提升很多了。
对数据管理的简化(Simplified data management):分区技术可以让DBA对数据的管理能力提升。通过优良的分区,DBA可以简化特定数据操作的执行方式。例如:DBA在对某些分区的内容进行删除的同时能保证余下的分区的数据完整性(这是跟对表的数据删除这种大动作做比较的)。
此外分区是由MySQL系统直接管理的,DBA不需要手工的去划分和维护。

Row-based replication
MySQL5.1以前的replication都是statement replication,它把在master端提交的语句记录到binlog并传播到它的各个salve服务器,slave服务器读取并翻译提交对应的statement语句。从5.1.5开始,MySQL就支持另一种复制手段:row-based replication。这种复制方式不同于statement replication,它在binlog中记录的是修改更新语句对MySQL数据表行数据的影响,实际上记录的是表结构信息和具体的各行数据信息。在5.1.8中还推出了两种方式的组合mixed形式的复制并做为MySQL 5.1的缺省复制模式。它默认采用statement replication,而只有在特别的情况下才采用row-based replication。
行复制的引入能够避免一些master和slave环境不同引起的问题的出现,所有的字段和对应的值都被复制到slave段,从而保持slave和master数据的一致性。

Plugin API.
MySQL5.1提供了一套灵活的plugin api,它可以在不重启服务器的基础上实时地装载和卸载各种不同的组件。这些plugin API可以包括(不限于):全文检索,存储引擎和服务器扩展等方面。例如:plugin full-text parsers就允许用户在索引文本上添加他们自己的输入过滤器,从而可以在PDF或者其他文件类型的文本上实现全文检索的目的。pre-parser full-text plugin将从文本中分析和抽取出具体的信息并传给MySQL本身的全文检索模块。

Event scheduler
事件调度器是在 MySQL 5.1中新增的另一个特色功能,可以作为定时任务调度器,取代部分原先只能用操作系统任务调度器才能完成的定时功能。例如,Linux中的crontab只能精确到每分钟执行一次,而MySQL的事件调度器则可以实现每秒钟执行一个任务,这在一些对实时性要求较高的环境下就非常实用了。
事件调度器是定时触发执行的,在这个角度上也可以称作是”临时的触发器”。触发器只是针对某个表产生的事件执行一些语句,而事件调度器则是在某一个 (间隔)时间执行一些语句。事件是由一个特定的线程来管理的,也就是所谓的”事件调度器”。启用事件调度器后,拥有 SUPER 权限的账户执行SHOW PROCESSLIST就可以看到这个线程了。通过设定全局变量event_scheduler 的值即可动态的控制事件调度器是否启用。

Server log tables
在版本5.1之前,MySQL的general query log和slow query log都是写在日志文件中的。5.1中就灵活多了。日志记录可以写在日志文件中,也可以写在mysql数据库中的表general_log和slow_log中。如果开启了logging的功能,用户可以选择它们其中的一个或者全都记录对应的日志信息。可以通过控制选项–log-output来决定日志信息的记录方式。

Upgrade program
mysql_upgrade工具可以检查所有现有数据表来查看它是否与现有的MySQL服务器的版本兼容,并且在必要的时候修复它们。在每一次MySQL升级时,都应该使用该工具来检查一下。

MySQL Cluster replication
Replication现在可以支持MySQL cluster之间的复制机制了,并且,现在也支持在MySQL cluster和非cluster之间的复制。

MySQL Cluster disk data storage
在MySQL 5.1.6版本以前,NDBCLUSTER存储引擎只能在内存中使用。之后,cluster的数据就可以存储在磁盘上了(不包括索引数据)。这使得MySQL cluster对内存的依赖减少了。
Improved backups for MySQL Cluster
在老版本的MySQL cluster中,cluster数据备份过程中单个节点的错误将导致整个备份过程的失败。但是新版本中不会出现这个问题。

MySQL Cluster NDB 6.x
在MySQL Cluster NDB 6.x中改进了很多并且还增加了一些新的特性。

Backup of tablespaces
mysqldump现在支持导出tablespaces的选项。可以使用-Y或者–all-tablespaces来启用该功能。

Improvements to INFORMATION_SCHEMA
相比5.0,5.1版本的MySQL在它的元数据数据库information_schema中提供了更多的信息。在这个数据库中新的数据表包括:FILES, EVENTS, PARTITIONS, PROCESSLIST, ENGINES, and PLUGINS.

XML functions with XPath support
在MySQL 5.1中,可以利用ExtractValue()返回匹配XPath串中XML片段的内容。也可以使用UpdateXML()来用一个XML片段元素来替换XPath串中的某一段XML片段元素,并返回替换后的串。

Load emulator
mysqlslap工具用来模拟客户端压力并报告每一步的时间消耗。它模拟很多个client连接MySQL server的情况。

非常规change master

最近做了一些搭建复制和迁移替换MySQL备机的工作。
特别记录下来MySQL非常规change master的小技巧。

1、问题1:
A<->B
C
A和B相互复制,应用访问A,现在需要搭建A到C的复制。A和B不对等,尽量避免应用切换到访问B。
回答:
在B上做备份,由于B是standby;不管你是做冷备,逻辑热备,逻辑冷备...都可以,把数据导入到C。
之后,搭建B到C的复制如下:
A <-> B -> C
这里停掉B的IO 线程,来确保B的SQL线程已经赶上IO线程,
此时,B不再赶A的复制,并且确定B到C的复制延迟都为0以后。
B和C的数据是保持完全一致的。
那么此时B复制到的位置就可以作为C change master 的位置。
简单写的脚本如下:
while read LINE; do
    OFFER_D_IP=`echo "$LINE" | awk '{print $1}'`
    OFFER_D_SOCK=`echo "$LINE" | awk '{print $2}'`

    SLAVE_STATUS_D=`ssh -n root@$OFFER_D_IP "mysql -S $OFFER_D_SOCK -uroot -pxxxx -e 'show slave status\G'"`
    OFFER_B_IP=`echo "$SLAVE_STATUS_D" | grep 'Master_Host:' | awk '{print $2}'`

    # stop io thread of offer b
    ssh -n root@$OFFER_B_IP "mysql -S /data/mysqldata/sock/mysql.sock -uroot -pxxxx -e 'stop slave io_thread'";

    # check if offer b, offer d slave have catch up
    #SLAVE_STATUS_D=`ssh -n root@$OFFER_D_IP "mysql -S $OFFER_D_SOCK -uroot -pxxxx -e 'show slave status\G'"`
    while [ 1 ]; do
        SECOND_BEHIND=`echo "$SLAVE_STATUS_D" | grep 'Seconds_Behind_Master:' | awk '{print $2}'`
        if [ $SECOND_BEHIND -eq 0 ]; then
            break
        fi
        sleep 1
    done
    SLAVE_STATUS_B=`ssh -n root@$OFFER_B_IP "mysql -S /data/mysqldata/sock/mysql.sock -uroot -pxxxx -e 'show slave status\G'"`
    while [ 1 ]; do
        SECOND_BEHIND=`echo "$SLAVE_STATUS_B" | grep 'Seconds_Behind_Master:' | awk '{print $2}'`
        if [ "x$SECOND_BEHIND" == "xNULL" ]; then
            break
        fi

        sleep 1
    done

    # build change master sql
    MASTER_HOST=`echo "$SLAVE_STATUS_B" | grep 'Master_Host:' | awk '{print $2}'`
    MASTER_LOG_FILE=`echo "$SLAVE_STATUS_B" | grep 'Relay_Master_Log_File:' | awk '{print $2}'`
    MASTER_LOG_POS=`echo "$SLAVE_STATUS_B" | grep 'Exec_Master_Log_Pos:' | awk '{print $2}'`
    CHANGE_MASTER_SQL="stop slave; CHANGE MASTER TO MASTER_HOST='$MASTER_HOST',    MASTER_PORT=3306,  MASTER_USER='repl',     MASTER_PASSWORD='xxxx',     MASTER_LOG_FILE='$MASTER_LOG_FILE',     MASTER_LOG_POS=$MASTER_LOG_POS;  start slave;"
    echo "$CHANGE_MASTER_SQL"

    # change master of offerd
    ssh -n root@$OFFER_D_IP "mysql -S $OFFER_D_SOCK -uroot -pxxxx -e \"$CHANGE_MASTER_SQL\""
    ssh -n root@$OFFER_D_IP "mysql -S $OFFER_D_SOCK -uroot -pxxxx -e 'show slave status\G'"

    # start offer d slave
    ssh -n root@$OFFER_B_IP "mysql -S /data/mysqldata/sock/mysql.sock -uroot -pxxxx -e 'start slave'"

done  <host.list
该脚本读取host.list参数文件获得C(OFFER_D)的IP和sock。B的IP通过C的show slave status获得。

问题2、
D <- A <-> B -> C
A和B互为主备,C为B的备机,D为A的备机。需要把C change master到D。形成:
C <- D <- A <-> B
的结构
回答:
这里我们在A上故意制造了binlog复制错误。
set sql_log_bin=0; use test; create table test_del (id int NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)); set sql_log_bin=1; drop table test_del;
使得B和D都停止在同一个复制位置。也就是说,此时B和D的数据是完全一致的。
这样在D上show master status\G就是C change master 的位置。
简单写了一个脚本如下:
while read LINE; do
    XY_OFFER_A_IP=`echo "$LINE" | awk '{print $1}'`
    XY_OFFER_B_IP=`echo "$LINE" | awk '{print $2}'`
    QD_OFFER_C_IP=`echo "$LINE" | awk '{print $5}'`
    QD_OFFER_C_SOCK=`echo "$LINE" | awk '{print $6}'`
    XY_OFFER_D_IP=`echo "$LINE" | awk '{print $7}'`
    XY_OFFER_D_SOCK=`echo "$LINE" | awk '{print $8}'`
    echo "$XY_OFFER_A_IP"
    echo "$XY_OFFER_B_IP"
    echo "$QD_OFFER_C_IP"

    MYSQL_ROOT_PASS="xxxx"

    ssh -n root@$XY_OFFER_A_IP "mysql -uroot -p$MYSQL_ROOT_PASS -e 'set sql_log_bin=0; use test; create table test_del (id int NOT NULL AUTO_INCREMENT, PRIMARY KEY(id)); set sql_log_bin=1; drop table test_del;'"

    while [ 1 ]; do
        XY_SLAVE_STATUS_D=`ssh -n root@$XY_OFFER_D_IP "mysql -S $XY_OFFER_D_SOCK -uroot -p$MYSQL_ROOT_PASS -e 'show slave status\G'"`
        SLAVE_SQL_STATUS=`echo "$XY_SLAVE_STATUS_D" | grep 'Slave_SQL_Running:' | awk '{print $2}'`
        if [ "x$SLAVE_SQL_STATUS" == "xNo" ]; then
            break
        fi
        sleep 1
    done

    while [ 1 ]; do
        XY_SLAVE_STATUS_B=`ssh -n root@$XY_OFFER_B_IP "mysql -S /data/mysqldata2/sock/mysql.sock -uroot -p$MYSQL_ROOT_PASS -e 'show slave status\G'"`
        SLAVE_SQL_STATUS=`echo "$XY_SLAVE_STATUS_B" | grep 'Slave_SQL_Running:' | awk '{print $2}'`
        if [ "x$SLAVE_SQL_STATUS" == "xNo" ]; then
            break
        fi
        sleep 1
    done

    # now we have xy-offer-d and xy-offer-b slave stop at the same place
    # we can now change master of qingdao-offer-c from xy-offer-b to xy-offer-d
    XY_MASTER_STATUS=`ssh -n root@$XY_OFFER_D_IP "mysql -S $XY_OFFER_D_SOCK -uroot -p$MYSQL_ROOT_PASS -e 'show master status\G'"`
    MASTER_LOG_FILE=`echo "$XY_MASTER_STATUS" | grep 'File:' | awk '{print $2}'`
    MASTER_LOG_POS=`echo "$XY_MASTER_STATUS" | grep 'Position:' | awk '{print $2}'`
    ssh -n root@$QD_OFFER_C_IP "mysql -S $QD_OFFER_C_SOCK -uroot -p$MYSQL_ROOT_PASS -e \"stop slave; CHANGE MASTER TO MASTER_HOST='$XY_OFFER_D_IP',    MASTER_PORT=3306,  MASTER_USER='repl',     MASTER_PASSWORD='xxxx',     MASTER_LOG_FILE='$MASTER_LOG_FILE',     MASTER_LOG_POS=$MASTER_LOG_POS;  start slave;\""

    # now we start the slave of xy offer b and xy offer d slave
    ssh  -n root@$XY_OFFER_D_IP "mysql -S $XY_OFFER_D_SOCK -uroot -p$MYSQL_ROOT_PASS  -e 'stop slave; SET GLOBAL sql_slave_skip_counter = 1; start slave;'";
    ssh  -n root@$XY_OFFER_B_IP "mysql -S /data/mysqldata2/sock/mysql.sock -uroot -p$MYSQL_ROOT_PASS  -e 'stop slave; SET GLOBAL sql_slave_skip_counter = 1; start slave;'";

done  <host.list
该脚本读取host.list参数文件获得A(XY_OFFER_A),B(XY_OFFER_B)的IP,C(QD_OFFER_C)的IP和sock,D(XY_OFFER_D)的IP和sock。

may your success

flashcache_load resource busy问题

使用fusion io和flashcache的时候遇到过两次
device-mapper: reload ioctl failed: Device or resource busy
Command failed
的异常。

第一次犯的错误是因为
flashcache_load mysql_data_cache /dev/fioa /dev/sdc1
前/dev/sdc1已经mount起来了。flashcache_load无法在已经mount的文件系统上再做cache。
解决的办法:
umount /dev/sdc1
然后按照正确的方法load起来。
正确的做法是对/dev/sdc分区,建立xfs(或者其他ext4,ext3)文件系统,然后利用flashcache_load将ssd设备和文件系统映射起来。
这样就会出现/dev/mapper/mysql_data_cache,将他用xfs(ext3,ext4)的方式mount起来。

第二次犯的错误是:
flashcache还在用,/dev/mapper/mysql_data_cache已经mount好了,把fusion-io的内核模块给卸载掉了。
这个时候flashcache_load会报错,/dev/mapper/mysql_data_cache也没有了,flashcache_create显示:
#flashcache_create mysql_data_cache /dev/fioa /dev/sdc1
cachedev mysql_data_cache, ssd_devname /dev/fioa, disk_devname /dev/sdc1
block_size 8, cache_size 0
flashcache_create: Valid Flashcache already exists on /dev/fioa
flashcache_create: Use flashcache_destroy first and then create again /dev/fioa
dmsetup显示:
#dmsetup table
mysql_data_cache:
解决方案:
dmsetup remove mysql_data_cache
flashcache_load mysql_data_cache /dev/fioa /dev/sdc1
mount -o defaults,rw,noatime,nodiratime,noikeep,nobarrier,allocsize=512M,attr2,largeio,inode64,swalloc /dev/mapper/mysql_data_cache /data2
使用最基本的dmsetup remove来清理mysql_data_cache,然后就可以flashcache_load了。
正常情况下,你最好先flashcache_destroy,然后再来操作fusion io,跟你建立的顺序相反

may your success

MySQL机器配置标准

最近我们部门在整理MySQL的配置标准。主要包括:
一、MySQL使用percona需要新增和调整的参数
二、使用了fusion io和flashcache后,对linux操作系统的配置和内核参数配置
三、由于使用了两个网卡,raid卡和drac卡等相关硬件也需要确认配置
详细信息请参考http://www.hellodb.net/http://www.penglixun.com/的相关文章,敬请期待

Mysql配置:

amysql版本:

percona-custom-5.1.57-12.8 采用icc编译。

 

bmysql配置文件新增:

my.cnf在原有的增加percona,xtradb相关配置

# New

innodb_support_xa = OFF

transaction_isolation = READ-COMMITTED

# innodb plugin

innodb_read_io_threads = 1

innodb_write_io_threads = 16

innodb_io_capacity = 40000

innodb_file_format = barracuda

innodb_file_format_check = ON

innodb_strict_mode = 1

# Percona

innodb_page_size = 4K |4k ssd or 8k sas |16k 大字段,压缩表或者全表扫描应用。

innodb_extra_rsegments = 32 (根据并发情况可调整至64)

innodb_use_purge_thread = 8

innodb_stats_update_need_lock = 0

innodb_fast_checksum = 1

# percona For SSD

innodb_adaptive_checkpoint = 3

innodb_flush_neighbor_pages = 0

innodb_adaptive_flushing = false

 

# Hander Socket

#loose_handlersocket_port = 9998

#loose_handlersocket_port_wr = 9999

#loose_handlersocket_threads = 1

#loose_handlersocket_threads_wr = 1

#loose_handlersocket_readsize = 1M

#loose_handlersocket_rcvbuf = 4M

#loose_handlersocket_sndbuf = 4M

#open_files_limit = 65535

 

c、报警和状态监控增加:无

 

 

linux操作系配置:

杂项

asys 文件系统设置

echo ’16′ > /sys/block/sdb/queue/read_ahead_kb

echo ’512′ > /sys/block/sdb/queue/nr_requests

echo ‘deadline’ > /sys/block/sdb/queue/scheduler

echo ’16′ > /sys/block/sdc/queue/read_ahead_kb

echo ’512′ > /sys/block/sdc/queue/nr_requests

echo ‘deadline’ > /sys/block/sdc/queue/scheduler

Fusion io attach上来就是noop,其他参数不修改。

rc.local添加开机自动设置。

 

bulimit限制

打开文件限制。open file limit。目前是10240

max locked memory限制。Unlimited

 

c、大页使用以及内存swap

使用大页的系统,为连接和操作系统预留8G以上。

sysctl.conf增加swappness=0

 

d、报警和状态监控增加:无

 

xfs配置:

amkfs操作

mkfs.xfs -f -i size=512,attr=2 -l lazy-count=1 -d su=1M,sw=2 -L /data1 /dev/sdb1

mkfs.xfs -f -i size=512,attr=2 -l lazy-count=1 -d su=1M,sw=10 -L /data2 /dev/sdc1

不采用flashcache的机器su采用raid 条带大小一般为64k.

采用flashcachesu使用raid卡条带大小(1M)sw采用读的时候磁盘数(比如10块盘,raid 1+0则为10raid5则为9)

 

bmount文件系统

mount -o defaults,rw,noatime,nodiratime,noikeep,nobarrier,allocsize=512M,attr2,largeio,inode64,swalloc LABEL=/redo /redo

mount -o defaults,rw,noatime,nodiratime,noikeep,nobarrier,allocsize=8M,attr2,largeio,inode64,swalloc LABEL=/ibddata /ibddata

/redo中存放:binloginnodb_loginnodb_tslogsockrelaylogslowlog

/ibddata中存放数据文件:mydatatmpdir

mysql的主文件目录/data/mysqldata 采用链接的方式链接到/redo/ibddata目录的各个子目录。

 

csysctl配置

xfs sysctl参数采用默认值,下面列出目前的xfs参数列表及默认值

#sysctl fs.xfs

fs.xfs.stats_clear = 0

fs.xfs.filestream_centisecs = 3000

fs.xfs.inherit_nodefrag = 1

fs.xfs.rotorstep = 1

fs.xfs.inherit_nosymlinks = 0

fs.xfs.age_buffer_centisecs = 1500

fs.xfs.xfsbufd_centisecs = 100

fs.xfs.inherit_noatime = 1

fs.xfs.inherit_nodump = 1

fs.xfs.inherit_sync = 1

fs.xfs.xfssyncd_centisecs = 3000

fs.xfs.error_level = 3

fs.xfs.panic_mask = 0

fs.xfs.irix_symlink_mode = 0

fs.xfs.irix_sgid_inherit = 0

fs.xfs.restrict_chown = 1

 

d、报警和状态监控增加:无

 

flashcache 配置

a、创建cache以及开机载入cache

第一次创建:flashcache_create mysql_data_cache /dev/fioa /dev/sdc1

开机重启时载入:flashcache_load mysql_data_cache /dev/fioa /dev/sdc1

blocksize设置为4k,为默认值。该值采用和perconapage_size一致大小

 

bsysctl配置:

需要修改的四个参数:

dev.flashcache.fast_remove = 1

dev.flashcache.reclaim_policy = 1

dev.flashcache.dirty_thresh_pct = 90

dev.flashcache.cache_all = 1

这些参数直接在/etc/sysctl.conf中修改。

 

下面列出flashcache所有的sysctl参数:

#sysctl dev.flashcache

dev.flashcache.cache_all = 0

dev.flashcache.fast_remove = 1

dev.flashcache.reclaim_policy = 0

dev.flashcache.pid_expiry_secs = 60

dev.flashcache.max_pids = 100

dev.flashcache.do_pid_expiry = 0

dev.flashcache.max_clean_ios_set = 2

dev.flashcache.max_clean_ios_total = 4

dev.flashcache.dirty_thresh_pct = 90

 

以下三个是用于控制flashcache的命令,可以利用这三个参数

dev.flashcache.stop_sync = 0

dev.flashcache.do_sync = 0

dev.flashcache.zero_stats = 0

 

c、报警和状态监控:

命令:

dmsetup status mysql_data_cache

性能监控状态值为:

read hit percent(99) write hit percent(51) dirty write hit percent(44)

 

命令:

dmsetup table mysql_data_cache

性能监控状态值为:

cache percent(98) dirty percent(88)

上面五个百分比在一张图中展示。

 

fusion io 配置

a、内核参数调整:

use_workqueue=0

disable-msi=0

use_large_pcie_rx_buffer=1

其他内核模块参数值采用默认。

这些内核参数直接通过在/etc/modprobe.d/iomemory-vsl.conf配置中新增:

options iomemory-vsl use_workqueue=0

options iomemory-vsl disable-msi=0

options iomemory-vsl use_large_pcie_rx_buffer=1

来添加,文件中其他参数不予调整

 

列出flashcache所有内核参数如下:

parm: enable_ecc:int

parm: enable_two_plane:int

parm: disable_msi:int

parm: bypass_ecc:int

parm: force_soft_ecc:int

parm: bypass_whitening:int

parm: dont_whiten:int

parm: force_sw_read_completions:int

parm: ecc_correction_target_threshold:int

parm: ecc_correction_per_pad_retire:int

parm: ecc_correction_retire_threshold:int

parm: preallocate_memory:Cards for which to preallocate memory

(card <serial> serial number required) (array of charp)

parm: preallocate_mb:int

parm: expected_io_size:int

parm: iodrive_load_midprom:int

parm: iodrive_load_eb_map:int

parm: iodrive_scan_nv_data:int

parm: tcmd0:int

parm: tcmd1:int

parm: tread0:int

parm: tread1:int

parm: twrite0:int

parm: twrite1:int

parm: taddr0:int

parm: taddr1:int

parm: tintr_hw_wait:int

parm: iodrive_tread_hw_wait:int

parm: iodrive_tread_hw_wait_mlc:int

parm: iodrive_tstat_hw_wait:int

parm: iodrive_tstat_hw_wait_mlc:int

parm: iodrive_dma_delay:int

parm: use_large_pcie_rx_buffer:int

parm: use_workqueue:int

parm: default_gc_low_water:int

parm: default_gc_high_water:int

parm: always_rebuild_md:int

parm: auto_attach:int

parm: auto_attach_cache:int

parm: parallel_attach:int

parm: disable_groomer:int

parm: groomer_backoff:int

parm: use_new_io_sched:int

parm: max_md_blocks_per_device:int

parm: strict_sync:int

parm: use_command_timeouts:int

parm: fio_dont_init:int

parm: max_requests:int

parm: reduced_write_threshold:int

parm: capacity_warning_threshold:int

parm: read_only_threshold:int

parm: iodrive_read_retire_threshold:int

parm: disable_rle:int

parm: force_minimal_mode:int

parm: early_oom_threshold:int

parm: flashback_mode:int

parm: flashback_warning_as_failure:int

parm: fio_dev_wait_timeout_secs:int

parm: fio_dev_optimal_blk_size:int

parm: exclude_devices:PCI addresses of devices to exclude during initialization

(full <domain>:<bus>:<slot>.<func> address required) (array of charp)

parm: include_devices:Only initialize devices with these PCI addresses

(full <domain>:<bus>:<slot>.<func> address required) (precedence over exclude_devices) (array of charp)

parm: thermal_throttle_disable:int

parm: compaction_timeout_ms:int

parm: persistent_discard:int

parm: debug_DBGS_DIGEST:uint

parm: debug_DBGS_DMA:uint

parm: debug_DBGS_ECC:uint

parm: debug_DBGS_GENERAL:uint

parm: debug_DBGS_GROOM:uint

parm: debug_DBGS_INJECT:uint

parm: debug_DBGS_LOG_FILE:uint

parm: debug_DBGS_LRBTREE:uint

parm: debug_DBGS_MEDIA_ERROR:uint

parm: debug_DBGS_METADATA:uint

parm: debug_DBGS_PCIE:uint

parm: debug_DBGS_PTRIM:uint

parm: debug_DBGS_REQUEST:uint

parm: debug_DBGS_SHOW_INJECT:uint

parm: debug_FIND_BUG_DA:uint

parm: debug_FIO_PRINT_DANGLING:uint

parm: debug_FIO_PRINT_DIGEST:uint

parm: debug_FIO_PRINT_OBJECT:uint

parm: debug_PRINT_APPEND_FAILURES:uint

parm: debug_PRINT_APPEND_POINT:uint

parm: debug_PRINT_DEPACKETIZER:uint

parm: debug_PRINT_DMA:uint

parm: debug_PRINT_DMA_READ:uint

parm: debug_PRINT_DMA_WRITE:uint

parm: debug_PRINT_ECC_READ:uint

parm: debug_PRINT_ECC_WRITE:uint

parm: debug_PRINT_GROOM_RANGES:uint

parm: debug_PRINT_GROOM_SCAN:uint

parm: debug_PRINT_IDLE_GROOM:uint

parm: debug_PRINT_LEB_OPERATIONS:uint

parm: debug_PRINT_NAND_READ:uint

parm: debug_PRINT_NAND_READ_DETAILS:uint

parm: debug_PRINT_NAND_WRITE:uint

parm: debug_PRINT_PACKETIZER:uint

parm: debug_PRINT_PARITY_OPERATIONS:uint

parm: debug_PRINT_PROGRESS:uint

parm: debug_PRINT_REATTACH:uint

parm: debug_PRINT_REQUESTS:uint

parm: debug_PRINT_REQUEST_LIST:uint

parm: debug_PRINT_RESOURCES:uint

parm: debug_PRINT_SCAN:uint

parm: debug_PRINT_SCAN_ENTRIES:uint

 

b、报警和状态监控:

命令:

fio-status -fk -an /dev/fct0

报警监控:

media_status=Healthy。非healthy报警

 

性能监控:

logical_written_bytes=2664888862208

logical_read_bytes=171877629608448

physical_written_bytes=27684857382680

physical_read_bytes=223401928291768

监控每隔一段时间的变化量而不是这个总量。

 

命令:

fio-get-erase-count -s /dev/fct0

性能监控:

Max: 149

Avg: 79.00

监控活动的block刷写的最大次数以及平均刷写次数

 

fio-get-erase-count -b -s /dev/fct0

Total blocks: 29

监控坏块的个数。

 

硬件相配置

网卡配置:

a、网卡绑定和IP分配

两块网卡,两两交叉配置bond

机器上有几个MySQL实例配置几个IP。各个IP在两个bond0上平均分配

另外增加一个专门的主机监控IP

 

b、网卡中断

网卡中断不绑定到CPU上。

 

c、报警和状态监控:

主机监控IP主要用来做mysql_host主机监控

各个实例IP监控用来监控数据库状态。

 

Numactl配置:

a、单机单实例关闭numa。在内核中直接关闭

多实例情况下,numa内存分配采用bind

采用在my.cnf中的[mysqld_safe]组中添加

mysqld=mysqld_using_numactl

来使用多实例MySQL绑定CPU的目的。

这里列出numa可能的配置选项:

default bind interleave preferred

 

b、增加的报警和状态监控:无

 

 

raid配置:

a、条带大小

raid配置界面,提交装机申请的时候指定,

flashcache设置条带设置为1MSAS盘采用默认64K

 

bLSI raid卡设置

/opt/MegaRAID/MegaCli/MegaCli -LDSetProp -CachedBadBBU -Lall -aALL

/opt/MegaRAID/MegaCli/MegaCli -LDSetProp -DisDskCache -Lall -aALL

/opt/MegaRAID/MegaCli/MegaCli -LDSetProp -NORA -Lall -aALL

/opt/MegaRAID/MegaCli/MegaCli -LDSetProp -WB -Lall -aALL

/opt/MegaRAID/MegaCli/MegaCli -LDSetProp -Direct -Lall -aALL

设置电池断电的时候仍然使用cache;不使用磁盘cache;不进行预读;设置为write back;设置为direct

(hp的机器暂时不管)

增加报警和状态监控:无

 

drac卡配置:

运行local_hw_oob_init.sh脚本,使得机器可以通过ipmi连接屏幕并通过ipmitool工具重启。

报警和状态监控:无

 

linux内核模

/etc/sysconfig/modules新增脚本:

fio.modules flashcache.modules xfs.modules

使得xfs,iomemory-vsl,flashcache开机自动载入

 

附:

block size设置规则:

mySQLraid卡,目前我们需要设置:

aperconapage size(ssd机器为4k , sas则设为8k ,大字段,压缩表或者全表扫描应用则设置为16k)

bflash cacheflashcache_create创建cache时的 block size(默认为4k)

cfusion iofio-format block size(默认不使用fio-format重新格式化fusion io)

dxfssu条带大小(xfs建议自己指定su条带大小,默认值一般不好)

eraid卡条带大小(默认值64K)

 

block size的相互关系如下:

1percona page size根据机器类型和应用类型来设置。

2flashcache_createblock size指定为percona page size一样的大小

3、一般情况下不使用fio-format重新格式化fusion io

4raid卡条带大小flashcache机器设置条带设置为1M,如果是SAS盘采用默认64K

5xfssu条带大小跟raid卡条带大小一样,并且应该为percona page size的整数倍。sw采用读的时候磁盘数(比如10块盘,raid 1+0则为10raid5则为9)

 

 

 


may your success

mysql character_sets_dir

我们有一套环境使用的是MySQL的多实例,并且我们MySQL不是放在MySQL认为应该放的目录:/usr/local/mysql下,所以今天又一个悲剧了。
数据库主机创建了一个ascii为字符集的表,主机创建成功,但是传到备机执行的时候,出错:
110510 17:14:55 [Warning] Slave: Unknown character set: ‘ascii’ Error_code: 1115
也就是说备机没有ascii字符集。
好吧,那就SHOW CHARACTER SET来看看,确实没有。
但是主机确实是有的,主备机的SHOW CHARACTER SET是不一样的。。。

好吧,其实我们备机使用的是多实例,主机是单实例。并且备机的MySQL采用的是二进制包的绿色安装。
那么这里就有一个问题,我们使用的mysqld_multi启动MySQL时它采用的是什么样的默认配置,这样的配置是否都是正确的
我们其实并不是非常肯定。
这里ascii字符集就是一个问题。

mysql的字符集配置详细请见:http://dev.mysql.com/doc/refman/5.1/en/charset-configuration.html
这里我们的备机用mysqld_multi启动以后,
show variables like ‘character_sets_dir’;
显示为:/usr/local/mysql/share/charsets。
而这个目录根本就不存在。

解决这个问题其实有三个办法:
1、mkdir -p /usr/local/mysql/share/; ln -s /path/to/correct/share/charsets /usr/local/mysql/share/charsets。
2、修改mysqld_multi,使得指向正确的目录。(目前这个办法没有走通,有待跟进)
3、在my.cnf中添加:character_sets_dir=/path/to/correct/share/charsets/
由于这个参数是read-only的,你只能重启MySQL来使它生效了

唉,其实作为一个MySQL DBA,连MySQL的这些配套的脚本都没有详细的搞清楚,有点汗颜,需要好好看一下。
如果你嫌麻烦,还是建议你把MySQL的二进制包放在MySQL指定的/usr/local/mysql下把,避免意外。

may your success