半夜ATM机前看书的那位

导航

mysql 主从同步原理 转

 Replication 线程

   Mysql的 Replication 是一个异步的复制过程,从一个 Mysql instace(我们称之为 Master)复制到另一个 Mysql instance(我们称之 Slave)。在 Master 与 Slave 之间的实现整个复制过程主要由三个线程来完成,其中两个线程(Sql线程和IO线程)在 Slave 端,另外一个线程(IO线程)在 Master 端。

  要实现 MySQL 的 Replication ,首先必须打开 Master 端的Binary Log(mysql-bin.xxxxxx)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全 顺序的执行日志中所记录的各种操作。打开 MySQL 的 Binary Log 可以通过在启动 MySQL Server 的过程中使用 “—log-bin” 参数选项,或者在 my.cnf 配置文件中的 mysqld 参数组([mysqld]标识后的参数部分)增加 “log-bin” 参数项。

  MySQL 复制的基本过程如下:

  1. Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

   2. Master 接收到来自 Slave 的 IO 线程的请求后,通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置;

  3. Slave 的 IO 线程接收到信息后,将接收到的日志内容依次写入到 Slave 端的Relay Log文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master- info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”

   4. Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后,会马上解析该 Log 文件中的内容成为在 Master 端真实执行时候的那些可执行的 Query 语句,并在自身执行这些 Query。这样,实际上就是在 Master 端和 Slave 端执行了同样的 Query,所以两端的数据是完全一样的。

  实际上,在老版本中,MySQL 的复制实现在 Slave 端并不是由 SQL 线程和 IO 线程这两个线程共同协作而完成的,而是由单独的一个线程来完成所有的工作。但是 MySQL 的工程师们很快发现,这样做存在很大的风险和性能问题,主要如下:

   首先,如果通过一个单一的线程来独立实现这个工作的话,就使复制 Master 端的,Binary Log日志,以及解析这些日志,然后再在自身执行的这个过程成为一个串行的过程,性能自然会受到较大的限制,这种架构下的 Replication 的延迟自然就比较长了。

   其次,Slave 端的这个复制线程从 Master 端获取 Binary Log 过来之后,需要接着解析这些内容,还原成 Master 端所执行的原始 Query,然后在自身执行。在这个过程中,Master端很可能又已经产生了大量的变化并生成了大量的 Binary Log 信息。如果在这个阶段 Master 端的存储系统出现了无法修复的故障,那么在这个阶段所产生的所有变更都将永远的丢失,无法再找回来。这种潜在风险在Slave 端压力比较大的时候尤其突出,因为如果 Slave 压力比较大,解析日志以及应用这些日志所花费的时间自然就会更长一些,可能丢失的数据也就会更多。

   所以,在后期的改造中,新版本的 MySQL 为了尽量减小这个风险,并提高复制的性能,将 Slave 端的复制改为两个线程来完成,也就是前面所提到的 SQL 线程和 IO 线程。最早提出这个改进方案的是Yahoo!的一位工程师“Jeremy Zawodny”。通过这样的改造,这样既在很大程度上解决了性能问题,缩短了异步的延时时间,同时也减少了潜在的数据丢失量。

  当然,即使是换成了现在这样两个线程来协作处理之后,同样也还是存在 Slave 数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事务中,这些问题都是存在的。

  如果要完全避免这些问题,就只能用 MySQL 的 Cluster 来解决了。不过 MySQL的 Cluster 知道笔者写这部分内容的时候,仍然还是一个内存数 据库的解决方案,也就是需要将所有数据包括索引全部都 Load 到内存中,这样就对内存的要求就非常大的大,对于一般的大众化应用来说可实施性并不是太大。当然,在之前与 MySQL 的 CTO David 交流的时候得知,MySQL 现在正在不断改进其 Cluster 的实现,其中非常大的一个改动就是允许数据不用全部 Load 到内存中,而仅仅只是索引全部 Load 到内存中,我想信在完成该项改造之后的 MySQL Cluster 将会更加受人欢迎,可实施性也会更大。

 

 

 

 
Mysql原理及主从架构(转载)
 

Mysql的逻辑结构:

第一层:连接管理层 用户连接的认证,管理、安全等

第二层:核心部分。包括查询解析、分析、优化、缓存。存储过程、触发器、试图都在这个层次上实现管理

第三层:存储引擎层

补充:parses 解析,Mysql 对任何一个查询都会做解析;每一次sql查询请求,mysql先去检查缓存,若果没有缓存的话在做词法分析

存储引擎层主要通过storage API 与核心层连接起来

并发控制:运用读锁和写锁

 事务:经过ACID(原子性、一致性、隔离性、持久性)测试,符合的才是事务

 

Mysql 的存储引擎

Mysql的最大的工作特征:插件式的存储引擎。不同的存储引擎所使用的管理模块是不同的,备份和存储的方式也不同。引擎并不是管理数据库本身。而是管理数据库运行时的进程。作为公司来言可以开发自己的存储引擎。

   默认的myisam    不支持事务,不支持行及锁,不支持外键 ,支持表压缩、支持在线备份 

       参数 :key_buffer_size  设定存储myisam索引的缓冲大小。不能缓存数据,数据考操作系统缓存,默认8M大小,最大4G。

            Concurrent_insert 是否支持并发插入的,默认打开。0表示不允许、1表示允许并发写入但是不允许在行之间产生空隙,2允许产生空闲数据块。

(这些都在my.cnf中的mysqld段中写)

默认的支持事务的引擎(也是运用最广泛的)inodb

Memery : 类似一个临时的数据库,把数据可的表和更重信息建构在内存中,实现快速查询。

Merger 和myisam 结合起来的常用引擎,主要实现表的partion的

InoDB: 主要用来处理事务的,表存储在表空间中的;索引可提供非常快速的逐渐查找,行级别锁

NDB  主要提供NDB cluster ,提供集群的管理。

 

 

修改密码的三种方法:

1. 在shell  下    mysqladmin  -u user_name   -h  ip_addr  password ‘your_password’

2. mysql> set password for ‘username’@’hostname’=password(‘your_password’);

3. mysql> update user set password=PASSWORD(‘123456’) where USER=’username’ and HOST=’host_name’;

 

 

主从配置:

初始配置主从服务器方法
配置说明
这里所说的"初始配置主从服务器"指的是,已经安装好了MySQL数据库,第一次配置主从复制功能,主数据库中还没有历史数据,因此,如果 MySQL的数据目录下已经有多余的文件,比如二进制日志文件mysql- bin.*,master.info,relay-bin.*,relay-log.*,请先删除。
主从复制配置方法
创建复制帐号
在主服务器上创建复制帐号,授予相应的权限。注意,复制帐号的口令最好不要超过6位,而且不要带"#"等特殊字符。创建命令如下:

GRANT REPLICATION SLAVE ON *.* TO ‘帐号名称’@’%’ IDENTIFIED BY ‘口令’

比如:
    GRANT REPLICATION SLAVE ON *.* TO ‘repuser’@‘%’ IDENTIFIED BY ‘111111’

在主服务器的MySQL配置文件中添加选项,打开二进制日志记录功能
server-id = 16204
log-bin=mysql-bin
binlog-ignore-db=mysql
binlog-ignore-db=information_schema

 各个配置选项的说明如下:
server-id = 16204
服务器ID号,整数值,保证唯一标识一台服务器就可以
log-bin=mysql-bin
打开二进制日志
binlog-ignore-db=mysql
忽略mysql数据库复制
binlog-ignore-db=information_schema
忽略information_schema数据库复制

在从服务器的MySQL配置文件中添加相关复制选项
server-id =16214
master-host=172.20.16.204 
master-user= repuser
master-password=111111
relay-log=relay-bin
relay-log-index=relay-bin
replicate-ignore-db=mysql
replicate-ignore-db=information_schema

各个配置选项的说明如下:
server-id =16214
  服务器ID号,整数值,保证唯一标识一台服务器比如:16214
master-host=172.20.16.204
主服务器IP地址,比如:172.20.16.204
master-user= repuser
 主服务器上创建的复制用户帐号名称,比如以上创建的:repuser
master-password=111111
  主服务器上创建的复制用户帐号密码,比如以上创建的:111111
relay-log=relay-bin
  中继日志名称
relay-log-index=relay-bin
  中继索引文件名称
replicate-ignore-db=mysql
忽略mysql数据库复制
replicate-ignore-db=information_schema
  忽略information_schema数据库复制

重启服务器
先重启主服务器,起来后再重启从服务器

察看运行状态
在主服务器上执行命令:show master status\G 
在从服务器上执行命令:show slave status\G


 如果复制状态Slave_IO_Running,Slave_SQL_Running都为Yes,说明复制已经配置正确
     Slave_IO_Running: Yes
     Slave_SQL_Running: Yes


向已有主服务器配置一台新的从服务器
配置说明
这里所说的"从已有主服务器配置一台新的从服务器"指的是,主从服务器都已经安装好了MySQL数据库,主服务器已经在运行,需要增加一个新的从服务器,已经有很多历史数据需要复制到从服务器上。征对这样的应用场景,请按下列方法配置复制。

主从配置方法
打开主服务器二进制日志功能
如果主服务器的二进制日志记录功能没有打开,在MySQL配置参数文件(比如/etc/my.cnf)中添加选项,重启MySQL服务,打开二进制日志功能。
   server-id = 16204
log-bin=mysql-bin
binlog-ignore-db=mysql
binlog-ignore-db=information_schema

 各个配置选项的说明如下:
server-id = 16204
服务器ID号,整数值,保证唯一标识一台服务器就可以
log-bin=mysql-bin
打开二进制日志
binlog-ignore-db=mysql
忽略mysql数据库复制
binlog-ignore-db=information_schema
忽略information_schema数据库复制

创建复制帐号
在主服务器上创建复制帐号,授予相应的权限。注意,复制帐号的口令最好不要超过6位,而且不要带"#"等特殊字符。创建命令如下:

GRANT REPLICATION SLAVE ON *.* TO ‘帐号名称’@’%’ IDENTIFIED BY ‘口令’

比如:
    GRANT REPLICATION SLAVE ON *.* TO ‘repuser’@’%’ IDENTIFIED BY ‘111111’

备份主服务器的数据文件
备份主服务器的数据文件
执行以下命令,给主服务器所有表加锁,禁止继续写入数据:
    FLUSH TABLES WITH READ LOCK;

记录复制启动断点
执行以下命令,记录从服务器开始启动复制的断点,包括日志名和偏移量。
  mysql>SHOW MASTER STATUS;
比如:
  mysql> show master status\G
     mysql-bin.000025
     Position: 13729
     Binlog_Do_DB:
Binlog_Ignore_DB: mysql,information_schema,mysql,information_schema

日志文件名是:mysql-bin.000025
偏移量是:13729
      注意,从服务器将从这个位置开始复制。

-----------一下部分本人未作验证,mysiam可以直接复制表,innodb的处理有所不同----

打包备份主服务器数据文件
打包需要复制的数据库文件,如果数据库文件安装在/var/lib/mysql目录下,可以执行命令:
tar zcf /tmp/backup.tar.gz /var/lib/mysql

该命令将把/var/lib/mysql目录下所有的文件都打包,也包括MySQL的系统表,而系统表一般都是不需要同步到从服务器上的,所以最好选择你需要复制的数据库目录,进行打包就可以了,如需要复制两个数据库(PRIVATE_DB1 ,PRIVATE_DB2)到从服务器上,只要把这两个目录打包:
tar czf /tmp/backup.tar.gz PRIVATE_DB1 PRIVATE_DB2

主服务器表解锁
执行以下命令,解开主服务器的读锁,主服务器可以继续更新数据:
mysql> UNLOCK TABLES;

在从服务器上恢复主备份文件
在从服务器相应的数据库目录(比如:/var/lib/mysql)上恢复主服务器上备份的数据库文件,恢复时需要关闭从服务器的MySQL服务,比如:
Cd /var/lib/mysql
Tar xzf backup.tar.gz

启动从服务器,设置复制断点
在MySQL中执行以下命令,设置复制开始断点:
change master to master_user=‘repuser’,
     master_password=‘654321’ , master_host=‘172.20.16.204’,
     master_log_file=‘ mysql-bin.000025’,master_log_pos=13729;

  表示从日志文件mysql-bin.000025’,位置13729开始复制

察看复制状态
在从服务器上执行命令:show slave status\G

 如果复制状态Slave_IO_Running,Slave_SQL_Running都为Yes,说明复制已经配置正确

     Slave_IO_Running: Yes
     Slave_SQL_Running: Yes

 

 

posted on 2011-08-17 21:30  zhizhesky  阅读(513)  评论(0编辑  收藏  举报