Posts tagged ‘mysql’

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


非常规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

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

mysql培训课程详细列表

为了提高开发人员和部门内部MySQL使用的技能和深度,我们特别制作了一些开发培训的计划,下面是一些主题

mysql应用开发培训
mysql安装的三种方式:rpm安装,tar.gz安装,configure安装
mysql 数据类型和函数,字节数,最大最小值,
mysql 适用SQL和不适用SQL。哪些SQL应该杜绝,哪些SQL应该避免,哪些在oracle适用但是尽量避免在MySQL中使用。
mysql 索引,约束,索引是否越多越好,覆盖索引,主键索引。
mysql 自定义函数以及procedure。delimiter,游标,调用,
mysql 视图,子查询,连接,union。不使用视图的原因,子查询的弊端,替换方案,内联接,外联接,union all和union的区别,使用场景。
mysql 分页limit,以及简单的实现原理
mysql 存储引擎介绍和比较。至少包括innodb,MyISAM,csv,memory,federated,ndb

mysql管理维护培训
mysql 备份和恢复。包括物理冷备;mysqldump; select into outfile;xtrabackup备份,优缺点,限制和使用场景。
mysql 复制搭建。步骤:备份并恢复数据;获得主机备份位置的binlog;change master
mysql binlog介绍。三种格式,分别的优缺点,statement复制的安全问题,row方式下目前我们遇到的几个问题。
mysql show processlist中,各个查询的状态的含义:query,NULL,executing,update等等。
mysql show engine innodb status介绍。
mysql show slave status输出详细解释。包括master.info,relay-log.info,logbin.index,relay-log.index, logbin.0001,relay-log.0001解释,slave io和slave sql 的不同状态含义
mysql 用户权限介绍。localhost,127.0.0.1,%的不同点。限制IP,限制数据库,限制表,限制字段,数据库或者表等的单字匹配以及多字匹配。
mysql 工具介绍:目前我们使用比较频繁的工具:mysql;mysqld_safe;mysqladmin;mysqlcheck;mysql_install_db;mysqlbinlog;mysqldump;mysqld_multi;以及第三方工具innotop;maatkit;mysqlsla
mysql my.cnf介绍。作用,mysql默认的位置,组的概念,工具特定参数介绍。
mysql 多实例概念和管理
mysql information_schema介绍,peconar新增信息介绍。
mysql ’mysql‘schema介绍,对应表信息。
mysql cluster介绍,性能问题,内存问题。

mysql高级培训
mysql configure安装的配置参数
mysql 源码框架和文件介绍
mysql binlog格式,二进制解释。文件头,event分类,二进制格式。
innodb 物理文件格式介绍以及数据恢复方法,实用案例分析,最终导出数据展示。
innodb 锁介绍
mysql 参数介绍。
mysql 状态变量介绍.目前在性能视图中的变量有哪些
mysql 大事务情况下,show slave status锁分析,解决方案。
mysql 唯一约束和普通索引在加锁上的区别。

sql培训单独列出,不包含在这些内容里面

heartbeat替换集群中的一台主机

今天完成了替换双master其中一台主机的任务。特将具体过程记录下来以供以后参考。
背景描述:
a,b互为主备,a提供应用访问。c是a的备机,画一个最挫的图如下
a<->b
|
c
现在,我想用c替换掉b。
a和b是用heartbeat来做HA的,要求在替换主机过程中,应用不能停,对应用必须要透明。
方案:
我们采用修改b的IP,并停掉b。然后把c的hostname,IP修改为b的方法,顶替b来避免对应用的影响
1、停止主机a的slave。这个是为了避免c替换掉b的IP起来的时候,a从错误的位置开始复制binlog。因为b和c的binlog不可能为同一个位置
2、b修改Ip并停机。修改/etc/sysconfig/network-scripts/ifcfg-bond0中的IP;/etc/init.d/network restart重启网络;poweroff关机
3、用c顶替b。
a)修改主机名。利用hostname命令设置主机名;修改/etc/hosts中的节点名称;修改/etc/sysconfig/network中的主机名
b)修改IP.同2.
c)修改heartbeat。这里是比较关键的地方,经过详细测试得出:
一:如果是全新安装的机器,需要从主机a中拷贝ha.cf,authkey,cib.xml以及通过crm_uuid -w 生成正确的uuid
二:如果是从a拷贝过来的heartbeat,那么需要删除(我的安装目录为/usr/heartbeat):
/usr/heartbeat/var/lib/heartbeat/hostcache
/usr/heartbeat/var/lib/heartbeat/hb_uuid
/usr/heartbeat/var/lib/heartbeat/hb_generation
hostcache为缓存主备机节点以及uuid的地方,
hb_uuid为本节点的uuid,
hb_generation为主备机协商时握手的数值。
hb_uuid和hb_generation如果顶替的时候跟之前的节点不一样,那么主机就会报:heartbeat[11165]: 2011/03/21_18:19:40 ERROR: should_drop_message: attempted replay attack [jyl-idle-db3b]? [gen = 1245825415, curgen = 1245825416]错误。
hb_uuid需要用crm_uuid -w 来生成,不能由heartbeat默认生成。从主机a的/usr/heartbeat/var/lib/heartbeat/hostcache获得b机器的uuid,然后crm_uuid -w uuid生成。
具体的信息可以参照下面的介绍:
4.5.2. Heartbeat
The seven-step guide to replacing an existing cluster node:
Make sure the old node is completely stopped
Give the new machine the same hostname as the old one
Go to an active cluster node and look up the UUID for the old node in /var/lib/heartbeat/hostcache
Install the cluster software
Copy ha.cf and authkeys to the new node
On the new node, populate it’s UUID using crm_uuid -w and the UUID from step 2
Start the new cluster node
http://www.clusterlabs.org/doc/en-US/Pacemaker/1.0/html/Pacemaker_Explained/s-replace-heartbeat.html
4、主机a,change master 搭建c到a的复制(这里可以随意的在c上show master status获得位置,因为c是备机,它自己没有应用访问生成binlog)
5、启用c机器的heartbeat和MySQL。检查crm_resource的输出
may your success

利用MegaCli和smartCtl工具获得ssd盘使用情况

之前详细询问了intel工程师关于怎么获得ssd盘使用情况的信息,并在杭州核心集群offer获得使用了一年多的ssd盘机器信息,目前该批机器ssd盘基本上都只耗一滴血,非常健康。
这里简单描述一下,怎么利用MegaCli和smartCtl获得ssd盘使用情况
首先,由于我们的服务器是做了raid的,所以需要用MegaCli获得各个适配器下的各个磁盘的信息。(目前我们的MySQL机器基本只有一个适配器)MegaCli有很多参数,具体的用法就不详细介绍了。
这里我们用MegaCli -PDList –aALL获得所有的适配器的物理磁盘信息。
例如:
Enclosure Device ID: 32
Slot Number: 4
Device Id: 4
Sequence Number: 2
Media Error Count: 0
Other Error Count: 0
Predictive Failure Count: 0
Last Predictive Failure Event Seq Number: 0
Raw Size: 122880MB [0xf000000 Sectors]
Non Coerced Size: 122368MB [0xef00000 Sectors]
Coerced Size: 122368MB [0xef00000 Sectors]
Firmware state: Online
SAS Address(0): 0×1221000004000000
Connected Port Number: 4(path0)
Inquiry Data: ATA     INTEL SSDSA2M16002HACVPO944400FM160AGN
这个就是其中一块物理磁盘的信息。
我们可以看到它的适配器编号(Enclosure Device ID: 32),设备编号(Device Id: 4),磁盘大小(Raw Size: 122880MB [0xf000000 Sectors]),连接口(Connected Port Number: 5(path0)),上线状态(Firmware state: Online。也有可能是hotspare)以及磁盘信息(Inquiry Data: ATA     INTEL SSDSA2M16002HACVPO944400FM160AGN,intel的ssd盘)
然后,通过smartctl我们可以获得对应磁盘的具体信息。smartctl是smartmontools工具包中的其中一个工具。
注意:这里smartctl的版本需要比较新,比如5.1.40已上
smartctl -a -d megaraid,4 /dev/sdb
这里megaraid,4的4表示上面MegaCli输出中的Device Id: 4,也就是说我们希望读取物理磁盘4的磁盘信息。
ssd盘的输出信息和sas盘的输出信息不同,特别是在
Vendor Specific SMART Attributes with Thresholds:段。
该段有很多ssd盘独有的参数。具体的参数请参考intel的pdf文件。
这里截取杭州offer集群的一台机器信息作为参考:
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
3 Spin_Up_Time            0×0000   100   000   000    Old_age   Offline      -       0
4 Start_Stop_Count        0×0000   100   000   000    Old_age   Offline      -       0
5 Reallocated_Sector_Ct   0×0002   100   100   000    Old_age   Always       –       0
9 Power_On_Hours          0×0002   100   100   000    Old_age   Always       –       10362
12 Power_Cycle_Count       0×0002   100   100   000    Old_age   Always       –       62
192 Unsafe_Shutdown_Count   0×0002   100   100   000    Old_age   Always       –       44
232 Available_Reservd_Space 0×0003   100   100   010    Pre-fail  Always       –       0
233 Media_Wearout_Indicator 0×0002   099   099   000    Old_age   Always       –       0
225 Host_Writes_32MiB       0×0000   200   200   000    Old_age   Offline      -       1284966
226 Intel_Internal          0×0002   255   000   000    Old_age   Always       –       0
227 Intel_Internal          0×0002   000   000   000    Old_age   Always       –       0
228 Intel_Internal          0×0002   000   000   000    Old_age   Always       –       0
其中我们比较关注的有以下四点:
1、Media_Wearout_Indicator:    使用耗费,100为没有任何耗费; 表示SSD上NAND的擦写次数的程度,初始值为100,随着擦写次数的增加,开始线性递减,递减速度按照擦写次数从0到最大的比例。一旦这个值降低到 1,就不再降了,同时表示SSD上面已经有NAND的擦写次数到达了最大次数。这个时候建议需要备份数据,以及更换SSD。
上面的机器为099,按照100滴血算,目前只耗了1滴血
2、Reallocated_Sector_Ct: 出厂后产生的坏块个数, 初始值为100,如果有坏块,从1开始增加,每4个坏块增加1
这里offer的机器还没有任何坏块
3、Host_Writes_32MiB: 已写32MiB, 每写入65536个扇区raw value增加1。这个扇区还是个数量单位,512字节
比如:这块盘就是 1284966 * 65536 * 512 = 40155.1875 GB
注意到每个机器都有一块盘写的比较少,这块盘就是hotspare盘。
每台机器我们有7块ssd盘。其中6块盘做的raid 5,第7块盘做的hotspare。
4、Available_Reservd_Space: SSD上剩余的保留空间, 初始值为100,表示100%,阀值为10,递减到10表示保留空间已经不能再减少
offer的机器基本都没有什么降低。
这样我们就获得了ssd盘的使用情况。
这里我再把林总的计算ssd盘还能用多久的方法摘录如下:
从这些值还可以推算一些东西:
offer集群的SSD单块盘累计写入量大约是40T  VS offer集群基本上都在99-100,磨损的程度非常低(初始值是100)。
Intel的均匀磨损算法控制得很好,基本上保证了磨损程度是平均的。
假设SSD单盘实际100GB(64GB+保留容量)大小,写入量40TB的话,就是每块单盘经历了40TB/100GB=400次相当于全盘写一遍,去除第一次空盘时写入的量,还有399次应该是“擦除”-“写入”的过程,为计算简便,我们就认为已经擦写了400次了。再考虑磨损率最大仅有1%,则我们的SSD盘厂商保证可擦写次数>=400/0.01=40000次(这个数字也是非常靠谱的),于是可以推算出:
1.         咱们的盘至少还可以写入(40000-400)*100GB=3960TB的数据
2.         上线到现在超过半年了,按已有的使用率(半年写入40TB),还可以用3960TB/40/2=49.5年
什么概念呢?不出其他的问题,理论上offer集群的SSD盘极限可用50年,当然我们不会用那么久,也不能等磨损率99%了才去考虑换盘,但是用到磨损率50%也可25年之久,再考虑材料性能的衰减,至少用上3、5年肯定是没有问题的

mysql默认登录账户

前几天,一个测试的哥们来找我,问我mysql登录,如果不输入用户名,那么默认使用的那个账户登录,我一想,不就是当前你登录的账户吗?用whoami就可以得到。
但是,我错了!
我们测试了这样一个场景
场景1:先登录root账户,然后su – mysql,此时,mysql登录进去以后一看,还是以root账户登录mysql的
场景2:如果我们直接以mysql登录这台主机,输入mysql登录,提示是默认用mysql账户登录MySQL数据库的。
这样的话,我们怀疑su – mysql 把一些环境变量带到mysql账户中。但是检查了env和set输出的内容,却没有发现异常。
没辙了,请教传奇人物我们的系统管理员:库哥。检查来检查去,最后库哥通过strace为我们释疑了。
(可能我自己好好看看MySQL的源代码也可以看到原因,但是偷懒了,值得批评!)
原因如下:mysql获得默认账户是这样获得的,它首先readlink /proc/self/fd/0获得登录账户的pts,
类似于
[mysql@PLATQA153004 ~]$ readlink /proc/self/fd/0
/dev/pts/5
然后通过/var/run/utmp来获得对应的用户,/var/run/utmp不是纯文本文件,但是你用root登录主机和mysql登录主机可以明显看到对应的用户名是不一样的。
那么也就是说,mysql是以你登录主机的pts账户作为默认账户的,su 等操作对它都没有影响。
摘录几个man介绍如下:
/proc/self
This  directory  refers to the process accessing the /proc filesystem, and is identical to the /proc directory named by the process ID of the
same process.
/proc/[number]/fd
This  is  a subdirectory containing one entry for each file which the process has open, named by its file descriptor, and which is a symbolic
link to the actual file.  Thus, 0 is standard input, 1 standard output, 2 standard error, etc.
我们在linux上面经常用的0,1,2就在这里了,哈哈
In a multithreaded process, the contents of this directory are not available if the main thread has already terminated (typically by  calling
pthread_exit(3)).
Programs  that will take a filename, but will not take the standard input, and which write to a file, but will not send their output to stan-
dard output, can be effectively foiled this way, assuming that -i is the flag designating an input file and -o is  the  flag  designating  an
output file:
foobar -i /proc/self/fd/0 -o /proc/self/fd/1 …
and you have a working filter.
/proc/self/fd/N  is  approximately  the  same  as /dev/fd/N in some UNIX and UNIX-like systems.  Most Linux MAKEDEV scripts symbolically link
/dev/fd to /proc/self/fd, in fact.
The  utmp  file  allows  one  to  discover information about who is currently using the system.  There may be more users currently using the system,
because not all programs use utmp logging.

xtrabackup Bad file descriptor问题解决

一直使用xtrabackup来备份MySQL,之前也没有出过特别的问题,但是在备份我们的一个库的时候,出现了:Bad file descriptor的错误
具体错误类似如下:
InnoDB: Operating system error number 9 in a file operation.
InnoDB: Error number 9 means ‘Bad file descriptor’.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.1/en/operating-system-error-codes.html
InnoDB: File operation call: ‘close’.
InnoDB: Cannot continue operation.

仔细检查,发现用户的权限有点问题;修改好了以后,再次备份,还是有问题。
然后看看这个机器跟其他机器的不同点:他的数据文件是链接到另外的mount点的,但是这个为什么会影响xtrabackup出错真是搞不懂。
有问题找google,还好搜到一篇好文章,有人也碰到了这个问题。

https://bugs.launchpad.net/percona-xtrabackup/+bug/568087

问题一样,还有人解决了,一直追到:http://bazaar.launchpad.net/~percona-dev/percona-xtrabackup/trunk/revision/133
仔细一看,这个版本是release版本之后的修改,也就是说,现成的rpm包我们是没有办法用了。
只好自己编译。
好吧,那就自己编译,还好之前在solaris上编译有经验。
这里也简单记录一下编译的一些步骤:
1、133版 http://bazaar.launchpad.net/~percona-dev/percona-xtrabackup/trunk/revision/133 下只有xtrabackup.c下载,我们可以自己到http://launchpad.net/percona-xtrabackup/release-1.2/1.2/+download/xtrabackup-1.2.tar.gz下载1.2版的源码。并把里面的xtrabackup.c替换掉。
2、xtrabackup-1.2/utils对应的目录里面有build51tree.sh, buildtree.sh分别是在linux下编译5.0和5.1版xtrabackup的脚本
3、正常的话,按照xtrabackup-1.2/Makefile里面的默认的配置是MySQL Plugin并使用XTRADB。而我并不想这样,所以我注释掉了DEFS+=  -DXTRADB_BASED和#MySQL Plugin下面的那些编译项。但是编译还是报错,查看了之前solaris编译时的注意实现发现要注释掉#MySQL 5.1下的第二个INNODBOBJS=。不知道为什么Makefile这边有两个这样的INNODBOBJS=,管它,注释掉第二个以后编译就成功。
用新版本备份,备份成功。

其实后面看了一下这个版本修改的代码:
2326
2326

2327
2327
/* close */
2328
2328
printf(“        …done\n”);
2329

os_file_close(src_file);

2329
if (!node->open) {

2330
os_file_close(src_file);

2331
}
2330
2332
os_file_close(dst_file);
2331
2333
ut_free(buf2);
2332
2334
return(FALSE);
2333
2335
error:
2334

if (src_file != -1)

2336
if (src_file != -1 && !node->open)
2335
2337
os_file_close(src_file);
2336
2338
if (dst_file != -1)
2337
2339
os_file_close(dst_file);
就那么几行,是因为没有判断节点是否还打开,结果导致出错,唉,程序的异常处理确实需要比程序本身的逻辑复杂很多啊。
不过还是没有想明白为什么这台机器就有问题,其他的都没有问题。

may your success.

主备备的两个备机转为双master时出现的诡异slave lag问题

有三台MySQL服务器,a,b和c,复制关系为 a -> b -> c。a,b,c的server_id分别为1,2,3
因为需要切换为 a b <-> c,也就是说,a单独出来,b和c作为双master结构时。
这种切换会经常出现在需要搭建备机把数据备份出来,然后把a独立出来的case中。

昨天,我就做了这样的切换,结果发现出现莫名奇妙的slave lag。
Seconds_Behind_Master一下子为0,一下子变成几千秒。
使用mysqlbinlog查看,binlog日志里面也有很多时间在几小时以前的event数据。
为了验证复制是否正常,我特别测试了一下,在b建一个表,并插入时间数据,到c上一看,表已经复制过来了,时间数据也是正确。
询问了一下同事,他说应该是MySQL的bug,在这种切换的情况下很容易触发这个bug,可以采用stop slave;change master; start slave;的方法来修复。但是实际的数据其实完全没有影响,复制还是正常的。

于是我按照这个办法:
stop slave io_thread;
stop slave;
show slave status\G
(这里先停io_thread是为了SQL thread和IO thread都执行到了同一个位置,change master 的时候没有风险)
stop slave;change master to … ; start slave;
(change master到show slave status的Master_Log_File:和Exec_Master_Log_Pos:位置,也就是说,其实根本没有改变复制的位置)

结果slave lag依然故我。这个问题就比较郁闷了。时间已经过了午夜,脑袋也转不动了,想过不管它了,反正复制没有问题。但是问题没有解决总觉得什么东西卡在喉咙一样。各种资料,各种变量都参考了一遍,最后,基本不太意识的输入:
show master logs;
show binlog events in ‘mysql-bin.000680′ from 34385301;
想看看最新产生的event,结果就发现不对的地方了。
这个最新产生的event有很多,并且server_id是1,1是a的server_id啊,应用访问的是b啊,怎么会在b上面产生a的server_id列,MySQL哪里出问题了?

仔细一想,明白了,事情是这样的:
a -> b -> c,a的event1(server_id为1)复制到b,也会复制到c,这个是正常的。
然后搭建c -> b的复制关系时,b需要断开a的连接,切换主库到c,在 change master 的位置在event1出现之前,那么event1肯定会被重新复制到b去,event1的server_id是1,那么b判断,这个event1不是我提交的,需要在本地执行,并且把它记录到了自己的binlog中;
由于b和c是双master结构,event1又复制到了c,c同样判断它不是我提交的,那么我需要在本地执行,并且记录到本地binlog中。
这样event1就在b和c之间循环往复,时间保持不变,MySQL的slave lag也就一下子是0,一下子是几千秒了。

这里,还需要说明一点,在环型复制里面,event之所以能够在环内只循环一次,而不是重复做,是因为提交的那个节点会发现这个event的server_id是自己的server_id,也就是说是自己提交的。那么,它就不会把这个event再应用一次,自然也不会记录到binlog。这个循环就结束了。除非你闲着没事做,设置了replicate-same-server-id参数。

那么解决问题怎么办列,很简单,把没有应用访问的c的server_id设置成a的server_id:
set global server_id=1;
看看时间差不多了,server_id为1的event都被干掉以后:
set global server_id=3;
然后再设置回来。
还好,MySQL 5.0和5.1的server_id都是动态的。

may your success.