zoukankan      html  css  js  c++  java
  • MySQL Replication 优化和技巧、常见故障解决方法

    MySQL 主从同步错误(error)解决(转)

    sql_slave_skip_counter参数


    附:
    一些错误信息的处理,主从服务器上的命令,及状态信息。
    在从服务器上使用show slave statusG

    Slave_IO_Running,为No,
    则说明IO_THREAD没有启动,请执行start slave io_thread

    Slave_SQL_Running为No
    则复制出错,查看Last_error字段排除错误后执行start slave sql_thread

    查看Slave_IO_State字段空 //复制没有启动
    Connecting to master//没有连接上master
    Waiting for master to send event//已经连上
    主服务器上的相关命令:
    show master status
    show slave hosts
    show logs
    show binlog events
    purge logs to 'log_name'
    purge logs before 'date'
    reset master(老版本flush master)
    set sql_log_bin=
     
    从服务器上的相关命令:
    slave start
    slave stop
    SLAVE STOP IO_THREAD //此线程把master段的日志写到本地
    SLAVE start IO_THREAD
    SLAVE STOP SQL_THREAD //此线程把写到本地的日志应用于数据库
    SLAVE start SQL_THREAD
    reset slave
    SET GLOBAL SQL_SLAVE_SKIP_COUNTER
    load data from master
    show slave status(SUPER,REPLICATION CLIENT)
    CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=,MASTER_USER=, MASTER_PASSWORD= //动态改变master信息
    PURGE MASTER [before 'date'] 删除master端已同步过的日志

    6.3.1 Master 同步线程状态
    以下列出了master的 Binlog Dump 线程 State 字段中最常见的几种状态。如果在master上没有 Binlog Dump 线程,那么同步就没有在运行。
    也就是说,没有slave连接上来。

    Sending binlog event to slave
    事件是由二进制日志构成,一个事件通常由更新语句加上其他信息。线程读取到一个事件并正发送到slave上。

    Finished reading one binlog; switching to next binlog
    读取完了一个二进制日志,正切换到下一个。

    Has sent all binlog to slave; waiting for binlog to be updated
    已经读取完全部未完成更新日志,并且全部都发送到slave了。它处于空闲状态,正等待在master上执行新的更新操作以在二进制日志中产生新
    的事件,然后读取它们。

    Waiting to finalize termination
    当前线程停止了,这个时间很短。
     
    6.3.2 Slave的I/O线程状态
    以下列出了slave的I/O线程 State 字段中最常见的几种状态。从MySQL 4.1.1开始,这个状态在执行 SHOW SLAVE STATUS 语句结果的
    Slave_IO_State 字段也会出现。这意味着可以只执行 SHOW SLAVE STATUS 语句就能了解到更多的信息。

    Connecting to master
    该线程证尝试连接到master上。

    Checking master version
    确定连接到master后出现的一个短暂的状态。

    Registering slave on master
    确定连接到master后出现的一个短暂的状态。

    Requesting binlog dump
    确定连接到master后出现的一个短暂的状态。该线程向master发送一个请求,告诉它要请求的二进制文件以及开始位置。

    Waiting to reconnect after a failed binlog dump request
    如果二进制日志转储(binary log dump)请求失败了(由于连接断开),该线程在休眠时进入这个状态,并定期重连。重连的时间间隔由 --
    master-connect-retry 选项来指定。

    Reconnecting after a failed binlog dump request
    该线程正尝试重连到master。

    Waiting for master to send event
    已经连接到master,正等待它发送二进制日志。如果master闲置时,这个状态可能会持续较长时间,如果它等待超过 slave_read_timeout 秒
    ,就会发生超时。这时,它就会考虑断开连接,然后尝试重连。

    Queueing master event to the relay log
    已经读取到一个事件,正把它拷贝到中继日志中以备SQL线程处理。

    Waiting to reconnect after a failed master event read
    读日志时发生错误(由于连接断开)。该线程在重连之前休眠 master-connect-retry 秒。
    Reconnecting after a failed master event read

    正尝试重连到master。当连接确定后,状态就变成 Waiting for master to send event。

    Waiting for the slave SQL thread to free enough relay log space
    relay_log_space_limit 的值非零,中继日志的大小总和超过这个值了。I/O线程等待SQL线程先处理中继日志然后删除它们以释放足够的空间

    Waiting for slave mutex on exit
    当前线程停止了,这个时间很短。
     
    6.3.3 Slave的SQL线程状态
    以下列出了slave的SQL线程 State 字段中最常见的几种状态:

    Reading event from the relay log
    从中继日志里读到一个事件以备执行。

    Has read all relay log; waiting for the slave I/O thread to update it
    已经处理完中继日志中的全部事件了,正等待I/O线程写入更新的日志。

    Waiting for slave mutex on exit
    当前线程停止了,这个时间很短。



    故障

    问题:主从复制不止何故停止了,我该怎么办?

    答案:复制错误多半是因为日志错误引起的,所以首先要搞清楚是主日志错误还是中继日志错误,从错误信息里一般就能判断,如果不能可以使用类似下面的mysqlbinlog命令:

    shell> mysqlbinlog <MASTER_BINLOG_FILE> > /dev/null

    shell> mysqlbinlog <SLAVE_BINLOG_FILE> > /dev/null

    如果没有错误,则不会有任何输出,反之如果有错误,则会显示出来。

    如果是主日志错误,则需要在从服务器使用SET GLOBAL sql_slave_skip_counter,如下:

    mysql> SET GLOBAL sql_slave_skip_counter = 1;

    mysql> START SLAVE;

    注:如果有多个错误,可能需要执行多次(提醒:主从服务器数据可能因此不一致)。

    如果是中继日志错误,只要在从服务器使用SHOW SLAVE STATUS结果中的日志信息重新CHANGE MASTER TO即可,系统会抛弃当前的中继日志,重新下载:

    mysql> CHANGE MASTER TO

    MASTER_LOG_FILE='<Relay_Master_Log_File>',

    MASTER_LOG_POS=<Exec_Master_Log_Pos>;

    mysql> START SLAVE;

    至于为什么使用的是Relay_Master_Log_File & Exec_Master_Log_Pos,参见概述。

    问题:主服务器宕机了,如何把从服务器提升会主服务器?

    答案:在一主多从的环境总,需选择数据最新的从服务器做新的主服务器。如下图所示:

    提升从服务器为主服务器

    在 一主(Server1)两从(Server2,、Server3)的环境中,Server1宕机后,等到Server1和Server2把宕机前同步到的 日志都执行完,比较Master_Log_File和Read_Master_Log_Pos就可以判断出谁快谁慢,因为Server2从 Server1同步的数据(1582)比Server3从Server1同步的数据(1493)新,所以应该提升Server2为新的主服务器,那么 Server3在CHANGE MASTER TO到Server2的时候应该使用什么样的参数呢?1582-1493=89,而Server2的最后的二进制日志位置是8167,所以答案是 8167-89=8078。

    技巧

    主 从服务器中的表可以使用不同的表类型。比如主服务器可以使用InnoDB表类型,提供事务,行锁等高级特性,从服务器可以使用MyISAM表类型,内存消 耗少,易备份等优点。还有一个例子,一台主服务器如果同时带很多个从服务器的话,势必会影响其性能,此时可以拿出一台服务器作为从服务器代理,使用 BLACKHOLE表类型,只记录日志,不写数据,由它带多台从服务器,从而提升性能。

    主从服务器中的表可以使用不同的键类型。比如主服务器用InnoDB,键用VARCHAR的话节省空间,从服务器使用MyISAM,键用CHAR提高速度,因为MyISAM有静态表一说。

    主从服务器中的表可以使用不同的索引。主服务器主要用来应付写操作,所以除了主键和唯一索引等保证数据关系的索引一般都可以不加,从服务器一般用来应付读操作,所以可以针对查询特征设置索引,再进一步,不同的从服务器可以针对不同的查询设置不同的索引。


    MySQL同步功能由3个线程(master上1个,slave上2个)来实现。执行 DE>START SLAVEDE> 语句后,slave就创建一个I/O线程。I/O线程连接到master上,并请求master发送二进制日志中的语句。master创建一个线程来把日 志的内容发送到slave上。这个线程在master上执行 DE>SHOW PROCESSLISTDE> 语句后的结果中的 DE>Binlog DumpDE> 线程便是。slave上的I/O线程读取master的 DE>Binlog DumpDE> 线程发送的语句,并且把它们拷贝到其数据目录下的中继日志(relay logs)中。第三个是SQL线程,salve用它来读取中继日志,然后执行它们来更新数据。

    如上所述,每个master/slave上都有3个线程。每个master上有多个线程,它为每个slave连接都创建一个线程,每个slave只有I/O和SQL线程。

    show slave master 用于提供有关从属服务器线程的关键参数的信息

    mysql> show slave status G;
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 172.17.2.40
    Master_User: photorepl
    Master_Port: 4331
    Connect_Retry: 60
    Master_Log_File: mysql-bin.005502
    Read_Master_Log_Pos: 64401238
    Relay_Log_File: mysqld-relay-bin.015418
    Relay_Log_Pos: 13456757
    Relay_Master_Log_File: mysql-bin.005152
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Replicate_Do_DB:
    Replicate_Ignore_DB: mysql
    Replicate_Do_Table:
    Replicate_Ignore_Table:
    Replicate_Wild_Do_Table: photo.%
    Replicate_Wild_Ignore_Table: mysql.%
    Last_Errno: 0
    Last_Error:
    Skip_Counter: 0
    Exec_Master_Log_Pos: 13456620
    Relay_Log_Space: 36764898503
    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: 249904
    ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

    SHOW SLAVE STATUS会返回以下字段:

    ? Slave_IO_State

    SHOW PROCESSLIST输出的State字段的拷贝。SHOW PROCESSLIST用于从属I/O线程。如果线程正在试图连接到主服务器,正在等待来自主服务器的时间或正在连接到主服务器等,本语句会通知您

    ? Master_User

    被用于连接主服务器的当前用户。

    ? Master_Port

    当前的主服务器接口。

    ? Connect_Retry

    –master-connect-retry选项的当前值

    ? Master_Log_File

    I/O线程当前正在读取的主服务器二进制日志文件的名称。

    ? Read_Master_Log_Pos

    在当前的主服务器二进制日志中,I/O线程已经读取的位置。

    ? Relay_Log_File

    SQL线程当前正在读取和执行的中继日志文件的名称。

    ? Relay_Log_Pos

    在当前的中继日志中,SQL线程已读取和执行的位置。

    ? Relay_Master_Log_File

    由SQL线程执行的包含多数近期事件的主服务器二进制日志文件的名称。

    ? Slave_IO_Running

    I/O线程是否被启动并成功地连接到主服务器上。

    ? Slave_SQL_Running

    SQL线程是否被启动。

    ? Replicate_Do_DB,Replicate_Ignore_DB

    使用–replicate-do-db和–replicate-ignore-db选项指定的数据库清单。

    ? Replicate_Do_Table,Replicate_Ignore_Table,Replicate_Wild_Do_Table,Replicate_Wild_Ignore_Table

    使用–replicate-do-table,–replicate-ignore-table,–replicate-wild-do-table和–replicate-wild-ignore_table选项指定的表清单。

    ? Last_Errno,Last_Error

    被多数最近被执行的查询返回的错误数量和错误消息。错误数量为0并且消息为空字符串意味着“没有错误”。如果Last_Error值不是空值,它也会在从属服务器的错误日志中作为消息显示。

    举例说明:

    Last_Errno: 1051

    Last_Error: error ‘Unknown table ‘z” on query ‘drop table z’

    该消息指示,表z曾经存在于在主服务器中并已被取消了,但是它没有在从属服务器中存在过,因此对于从属服务器,DROP TABLE失败。(举例说明,在设置复制时,如果您忘记了把此表拷贝到从属服务器中,则这有可能发生。)

    ? Skip_Counter

    最近被使用的用于SQL_SLAVE_SKIP_COUNTER的值。

    ? Exec_Master_Log_Pos

    来自主服务器的二进制日志的由SQL线程执行的上一个时间的位置(Relay_Master_Log_File)。在主服务器的二进制日志中的 (Relay_Master_Log_File, Exec_Master_Log_Pos)对应于在中继日志中的(Relay_Log_File,Relay_Log_Pos)。

    ? Relay_Log_Space

    所有原有的中继日志结合起来的总大小。

    ? Until_Condition,Until_Log_File,Until_Log_Pos

    在START SLAVE语句的UNTIL子句中指定的值。

    Until_Condition具有以下值:

    o 如果没有指定UNTIL子句,则没有值

    o 如果从属服务器正在读取,直到达到主服务器的二进制日志的给定位置为止,则值为Master

    o 如果从属服务器正在读取,直到达到其中继日志的给定位置为止,则值为Relay

    Until_Log_File和Until_Log_Pos用于指示日志文件名和位置值。日志文件名和位置值定义了SQL线程在哪个点中止执行。

    ? Master_SSL_Allowed,Master_SSL_CA_File,Master_SSL_CA_Path,Master_SSL_Cert,Master_SSL_Cipher,Master_SSL_Key

    这些字段显示了被从属服务器使用的参数。这些参数用于连接主服务器。

    Master_SSL_Allowed具有以下值:

    o 如果允许对主服务器进行SSL连接,则值为Yes

    o 如果不允许对主服务器进行SSL连接,则值为No

    o 如果允许SSL连接,但是从属服务器没有让SSL支持被启用,则值为Ignored。

    与SSL有关的字段的值对应于–master-ca,–master-capath,–master-cert,–master-cipher和–master-key选项

    ########################################################################

    Replication延时的类型

        1固定性的延时

        ——Slave的数据持续性的落后于Master并且一直无法与Master的数据保持一致。

        ——Slave的数据经常在白天落后于Master,而在晚上可以赶上并与Master的记录保持一致。

        这种类型的延时通常是由于Slave服务器的负载已经到达了上限或在白天访问量大的时候到达上限造成的。

        2非固定性的延时

        ——Slave的数据只是短暂的落后于Master,可在短时间内恢复这类型的延时通常与批量任务和报表有关,效率差的查询也会导致这类延时

        Mysql Replication的限制

          MysqlReplication是单线程的,意味着只能有效的使用一个CPU内核和一个磁盘,一条复杂的查询或者事务都导致进程被阻塞,不过现在针对5.1版本的多线程Replication补丁,http://forge.mysql.com/wiki/ReplicationFeatures/ParallelSlave,还是pre版,有很多限制,感兴趣的可以去看看。

        Replication的容量

        1理解什么是Replication的容量

          可以将Replication暂停一个小时,重新启动Replication后,观察Slave的数据多久可以与Master一致。从Replication重新启动到和Master数据一致所花费的时间与Replication暂停的时间的比值就是Replication的容量。

        2建议保持Replication的容量在3倍以上,即延迟一个小时的数据,Slave只需要20分钟就能与Master的数据一致。

        Replication的优化

        15.0mysql中避免类似以下的更新语句

        INSERT … SELECT

        UPDATE .... WHERE

          复杂的查询会导致Replication线程阻塞。如果是insertupdateselect结合的语句,可以讲select单独执行并保存在临时表中,然后再执行insert或者update

          如果使用的是5.1mysql,新功能中的行级ReplicationRBR)可以解决这个问题。RBR可以将在Master上通过复杂查询后更新的结果直接传给SlaveSlave可以直接将结果更新到数据库中。

        2避免大的事务

        太大的事务会造成Replication长时间阻塞,数据会严重滞后于Master

        Slave服务器的硬件选择

        更快的CPU内核,对于单线程的Replication多核CPU是没有任何优势的。更高速的硬盘,包括更高的转速和更好的高速缓存命中率,如果有钱的话上SSD吧。

        主从结构的扩展性问题

        1如何降低写操作的频率

          Master的写操作会扩散到所有的Slave上,所以高频率的写操作会降低Slave的读操作效率。

        至少保持一台Slave做全库同步,其他的Slave可以只做部分表的同步。当然,这需要web应用程序的配合来分配哪些查询读哪些Slave。将一些更新操作放到memcached中,例如session和计数器。Slave使用myisam引擎,将一些写入量很大的更新操作直接在slave上执行,而不通过Replication

        2如何更有效的利用Slave的硬件资源[ 变形虫]

        使用分区

        有选择的对表进行同步

        Slave上对数据进行归档。

        Session的持久化

        为不同的应用服务器分配不同的Slave进行读操作。

        或者根据查询类型的不同来分配不同的Slave

        3如何使你的程序最大化的利用Slave

          将对数据更新不敏感的查询放到Slave上,而需要实时数据的查询则放到Master。通过session的持久化,让做了修改的用户首先看到修改的内容,其他的用户可以等待Slave更新后再查看新内容。

          对于某些数据,可以用memcached来存放数据的版本号,读Slave的程序可以先对比Slave的数据和memcached数据的版本,如果不一致则去读master。用户和博客类的信息可以用这种方法。在查询前可以通过SHOW SLAVE STATUS检测Slave的状态,然后根据返回的结果进行服务器的选择。

    http://blog.csdn.net/adparking/article/details/7587147

  • 相关阅读:
    在FreeBSD中pkg包管理器使用实例
    租了一台华为云耀云服务器,却直接被封公网ip,而且是官方的bug导致!
    Java8 Stream对集合的一些应用
    idea 编码UTF-8 设置
    Java RSA非对称加密算法实现
    分库分表 策略 临时
    springboot+dubbo + zookeeper 案例
    跟着华为,学数字化转型(6):一把手工程
    跟着华为,学数字化转型(5):数据保护和业务决策
    跟着华为,学数字化转型(4):数据采集
  • 原文地址:https://www.cnblogs.com/seasonzone/p/5076508.html
Copyright © 2011-2022 走看看