155:主从复制的两个核心应用场景以及简单工作原理。
应用场景:
读写分离。在数据量大、IO压力大的情况下,可以搭建主从架构,进行读写分离,一般是主库负责写,从库负责读,以此来解决压力大的问题。
单点故障。在业务场景下,如果主库突然宕机了,业务就无法继续运行,即使有备份进行恢复也是需要时间的,为了防止这种情况的发生就可以搭建主从架构,一般主从的数据是近乎一致的,如果主库宕机,可以进行主库切换保证业务正常运行。
工作原理:
主从复制是一个异步复制的过程,从一个Mysqlmaster复制另外一个Mysql slave,在Master与 slave之间实现整个复制的过程是由三个线程来完成的,其中两个线程sql线程和IO线程在Slave端,另外一个线程IO线程在Master端。
156:mysql 主从复制两大延迟,描述两大延迟主要的延迟原因。
传输延迟:搭建主从复制的数据库如果位于不同的服务器,甚至说是跨机房,那么它们之间的IO就存在传输的问题,网络带宽、传输速度等就会影响主从之间传输的效率。
应用延迟:MySQL的主从复制是单线程操作,主库对于所有操作产生的binlog是顺序写入的,它和slave的IO线程到主库读取binlog的效率都很高,但是slave的SQL线程是单线程,它读取的操作不是顺序的是随机的,这就造成了很高的资源消耗;当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,就会发生等待,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。
157:相对详细的描述一下主从复制的原理,对应的线程,线程的资源消耗以及状态查看。
复制的基本过程如下:
1.Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
2.Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
3.Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
4.Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
主从的状态通过在slave上show slave status\G 查看。
158:描述一下主库binlog的删除策略以及对应的参数设置和实现语法、从库relay log 的删除策略。
因为binlog是一直记录的并且永久保存,所以会随着时间binlog文件的大小越来越多,占用大量的空间资源,所以需要定期进行删除。
主库binlog的删除可以在满足以下两个条件时进行:
从库同步成功,也就是说IO线程读取到slave上并且SQL线程执行完毕;
已经备份过的binlog;
删除有两种方法:
可以通过purge binary logs to 'bin.000012';命令来删除当前binlog文件之前的binlog文件,该命令也可以通过时间节点来删除;
通过设置set global expire_logs_days=8;参数来指定log的过期时间,该参数是全局变量,默认为0不过期,重启MySQL后会恢复默认,所以需要在my.cnf里添加;
relay log的删除要看具体业务场景,一般由参数relay_log_purge控制是否自动清空不再需要的中继日志,默认值为1(启用);但在一些场景里,例如MHA高可用架构中,在主库宕机切换的过程中,它需要备主用relay log来同步其他从库,所以就需要将该参数设置为0,后期进行手动删除relay log。
159: binlog 三 种 模 式 , 对 应 的 优 缺 点 , 特 殊 场 合 临 时 性 改 变 语 句 模 式 , set@@session.binlog_format='STATEMENT';。
1.Statement:每一条会修改数据的sql都会记录在binlog中。
优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。(相比row能节约多少性能与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条件的update操作,以及整表删除,alter表等操作,ROW格式会产生大量日志,因此在考虑是否使用ROW格式日志时应该跟据应用的实际情况,其所产生的日志量会增加多少,以及带来的IO性能问题。)
缺点:由于记录的只是执行语句,为了这些语句能在slave上正确运行,因此还必须记录每条语句在执行的时候的一些相关信息,以保证所有语句能在slave得到和在master端执行时候相同 的结果。另外mysql 的复制,像一些特定函数功能,slave可与master上要保持一致会有很多相关问题(如sleep()函数, last_insert_id(),以及user-defined functions(udf)会出现问题)。
使用以下函数的语句也无法被复制:
* LOAD_FILE()
* UUID()
* USER()
* FOUND_ROWS()
* SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)
同时在INSERT ...SELECT 会产生比 RBR 更多的行级锁。
2.Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。
优点: binlog中可以不记录执行的sql语句的上下文相关的信息,仅需要记录那一条记录被修改成什么了。所以rowlevel的日志内容会非常清楚的记录下每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题。
缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样造成binlog日志量会很大,特别是当执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。
3.Mixed: 是以上两种level的混合使用,一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种.新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录。至于update或者delete等修改数据的语句,还是会记录所有行的变更。
160:从库上两个 info 文件的名字和作用、重要性,为什么最好保存到表中,如何实现。
master.info:记录master的信息;
relay-log.info:记录slave应用binlog的信息;
从库复制主库的情况会记录在relay_log.info文件中,并且主从复制正常的情况下会一直进行刷新,可以直接通过查看该文件了解从库应用的状态值。
在5.6.2版本之后,这两个文件的信息被允许记录到表中,相对于文件来说,记录在表中更加的安全,效率也相对更高,参数设置如下:
master-info-repository = TABLE ---FILE表示以文件方式
relay-log-info-repository = TABLE ---FILE表示以文件方式
对应的表分别为mysql.slave_master_info与mysql.slave_relay_log_info,且这两个表均为innodb引擎表。
161:熟悉解读show slave status\G,对于 io 和 apply 线程的延迟和工作状态有一个清楚的理解。如何查看传输延迟和应用延迟?
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
字段解释:
Slave_IO_State
SHOW PROCESSLIST输出的State字段的拷贝。SHOWPROCESSLIST用于从属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值不是空值,它也会在从属服务器的错误日志中作为消息显示。
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具有以下值:
如果没有指定UNTIL子句,则没有值
如果从属服务器正在读取,直到达到主服务器的二进制日志的给定位置为止,则值为Master
如果从属服务器正在读取,直到达到其中继日志的给定位置为止,则值为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具有以下值:
如果允许对主服务器进行SSL连接,则值为Yes
如果不允许对主服务器进行SSL连接,则值为No
如果允许SSL连接,但是从属服务器没有让SSL支持被启用,则值为Ignored。
与SSL有关的字段的值对应于--master-ca,--master-capath,--master-cert,--master-cipher和--master-key选项的值。
Seconds_Behind_Master
本字段是从属服务器“落后”多少的一个指示。当从属SQL线程正在运行时(处理更新),本字段为在主服务器上由此线程执行的最近的一个事件的时间标记开始,已经过的秒数。当此线程被从属服务器I/O线程赶上,并进入闲置状态,等待来自I/O线程的更多的事件时,本字段为零。总之,本字段测量从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。
如果主服务器和从属服务器之间的网络连接较快,则从属服务器I/O线程会非常接近主服务器,所以本字段能够十分近似地指示,从属服务器SQL线程比主服务器落后多少。如果网络较慢,则这种指示不准确;从属SQL线程经常会赶上读取速度较慢地从属服务器I/O线程,因此,Seconds_Behind_Master经常显示值为0。即使I/O线程落后于主服务器时,也是如此。换句话说,本列只对速度快的网络有用。
即使主服务器和从属服务器不具有相同的时钟,时间差计算也会起作用(当从属服务器I/O线程启动时,计算时间差。并假定从此时以后,时间差保持不变)。如果从属SQL线程不运行,或者如果从属服务器I/O线程不运行或未与主服务器连接,则Seconds_Behind_Master为NULL(意义为“未知”)。举例说明,如果在重新连接之前,从属服务器I/O线程休眠了master-connect-retry秒,则显示NULL,因为从属服务器不知道主服务器正在做什么,也不能有把握地说落后多少。
162:一主多从架构的优缺点,多级复制的优缺点和多级复制中一级从库的设置要点。
一主多从
优点:
防止单点故障,可以进行主库切换;
读写分离减轻主库压力;
从库备份不影响主库效率;
防止单一数据库数据丢失;
从库可以使用不同的存储引擎,用于不同的性能需求;
缺点:由于SQL线程是单线程,会造成应用延迟,就会出现数据不一致现象。
多级复制
优点:同上,主库切换更加方便,直接提升1级从库为新主;
缺点:一级从库会显得尤其重要,如果出现宕机,主从结构就没有了,很容易出现单点故障,并且由于多级从库,延迟问题会更加严重。
一级从的要点:
开启log_slave_updates,保证读取的relay log写入自己的binlog,来让下一级从库进行读取。
163:搭建一个主从数据库,写脚本实现对主从数据库的同步状态监控:传输延迟、应用延迟。
164:半同步的实现机制和同步范围。
MySQL 5.5开始支持半同步复制(Semi-Sync MySQL Replication),半同步提供了更好的灾难恢复性。
半同步的原理是,主库和它的从库都启用半同步特性,当一个从库连接主库时标识自己是否支持半同步,如果主库启用了半同步,且拥有至少一个半同步从库,一个事务提交会阻塞直到确认至少一个半同步从库已经“接收到事务事件(event)”,否则一个“超时”发生。半同步从库在写入事件(event)到中继日志(relay log),刷新到磁盘后才确认“接收到事务事件”。如果一个“超时”发生,即没有任何一个半同步从库确认接收到事务事件,那么主库自动切换到异步复制模式。当至少一个半同步从库追赶上主库,主库自动切换到半同步模式。
这里的“半同步”,可以这样理解:
传统的异步同步,主库写事务事件到二进制日志,从库索取主库日志,这不能确保事务事件被传送到从库。而对于全同步(fully synchronous replication)复制,主库提交事务,必须等待从库也提交这个事务成功,才能完成这个事务,这样容易造成事务的延迟。所以,出现了半同步,半同步介于异步和全同步之间。
需要留意到是,半同步对于网络要求高,它仅适用于高速内网。虽然MySQL 5.5的半同步表现不佳,但是,据官方文档,在新的5.7版本中,它已经得到了改善。
165:如何实现半同步复制。
要想使用半同步复制,必须满足以下几个条件:
1. MySQL 5.5及以上版本
2. 变量have_dynamic_loading为YES
3. 异步复制已经存在
搭建过程:
首先加载插件
因用户需执行INSTALL PLUGIN, SETGLOBAL, STOP SLAVE和START SLAVE操作,所以用户需有SUPER权限。
主:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME'semisync_master.so';
从:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME'semisync_slave.so';
查看插件是否加载成功,有两种方式:
1.
mysql> show plugins;
rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL
2.
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROMINFORMATION_SCHEMA.PLUGINS WHEREPLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.00 sec)
启动半同步复制
在安装完插件后,半同步复制默认是关闭的,这时需设置参数来开启半同步
主:
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
从:
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
重启从上的IO线程
mysql> STOP SLAVE IO_THREAD;
mysql> START SLAVE IO_THREAD;
如果没有重启,则默认还是异步复制,重启后,slave会在master上注册为半同步复制的slave角色。
查看半同步是否在运行
主:
mysql> show status like'Rpl_semi_sync_master_status';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON |
+-----------------------------+-------+
1 row in set (0.00 sec)
从:
mysql> show status like 'Rpl_semi_sync_slave_status';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.20 sec)
这两个变量常用来监控主从是否运行在半同步复制模式下。
166:熟悉解读半同步复制状态值:show global status like '%rpl%';。
mysql> show status like '%Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 6 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 1120 |
| Rpl_semi_sync_master_tx_wait_time | 4483 |
| Rpl_semi_sync_master_tx_waits | 4 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 4 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
上述状态变量中,比较重要的有以下几个:
Rpl_semi_sync_master_clients:当前半同步复制从的个数,如果是一主多从的架构,并不包含异步复制从的个数。
Rpl_semi_sync_master_tx_avg_wait_time:事务因开启Semi_sync,平均需要额外等待的时间。
Rpl_semi_sync_master_net_avg_wait_time:事务进入等待队列后,到网络平均等待时间。
依据上面两个状态值可以知道,Semi-sync的网络消耗有多大,给某个事务带来的额外的消耗有多大。
Rpl_semi_sync_master_status 则表示当前Semi-sync是否正常工作。
从Rpl_semi_sync_master_no_times变量,可以知道一段时间内,Semi-sync是否有超时失败过,该计数器则记录了这样的失败次数。
167:如果主从之间网络出现问题,半同步复制的现象,以及自动处理的机制。
半同步复制对网络的要求比较高,它需要很高的速度来维持半同步的传输机制,如果出现了网络问题,就会造成主库等待从库确认超时,主库就会自动切换回异步复制;如果运行过程中,网络问题好了,从库的事务追了上来,主从中间可以自动恢复为半同步复制。
168:从库 read-only 启动,意义和实现。
mysql> set global read_only=1; #开启只读
从库的存在一般是为了给主库分压,承担读的任务,所以一般从库是没有写入操作的,我们开启read_only后,数据库就不允许进行任何的写入操作了,这样可以保障主从的一致性,如果在从库上误操作进行了写入,就可能造成数据不一致,导致主从复制无法正常执行。但是这个参数对具有超级权限的用户无效。
169:如何实现从库的分拆,将从库分拆成多个不一致的从库,分别同步不同的库或者表,事务层面的使用限制。
从库的复制是基于主库的binlog,通过读取主库的binlog到从库的relay log中,再用SQL线程去执行relay log中的内容,来实现主从复制。
如果要基于库和表进行同步,可以利用binlog的特性,可以只记录某个库某个表的数据来实现,从库只读取固定的库和表的binlog就可以实现很好的从库分拆了。
在事务层面,如果有多表或跨库操作,由于是同步的单库单表,事务就会报错进行回滚,造成阻塞或者数据不一致的现象。
replicate-do-table=表名:表示mysql启动的时候可以在mysqld_safe后面加这个参数.
170:从库如何处理 SQL 应用出现的错误,列举自动处理的方式以及对应的参数和实现。
自动处理的错误一般为锁冲突或者事务顺序写冲突,就会发生锁等待和事务等待的情况。
171:从库如何处理 SQL 应用出现的错误,列举手工干预方式,如何实现以及如何进行监控。
1. 在参数文件my.cnf中添加参数:
slave_skip_errors=X #可以跳过指定类型报错X的错误;
#slave-skip-errors=all #跳过所有错误
2. set globalsql_slave_skip_counter=N #该参数的意思是从库跳过N个event。