MYSQL的高级知识及AB复制

慢查询日志(slow query log)

mysql> show variables like '%log_slow%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| log_slow_queries | OFF   |是否打开slow query log功能,打开slow query log功能对系统性能的整体影响没有binlog那么大,毕竟slow query log的
+------------------+-------+数据量比较小,带来的IO损耗也就较小,但消耗总是会有一些的,主要是CPU方面的消耗。如果大家的系统CPU资源足够丰富,可以不必在乎这一点点损耗,毕竟它可能会带来更大性能优化方面的收获。但如果CPU资源比较紧张,完全可以在大部分时候关闭此功能,只须要间断性地打开此功能来定位可能存在的慢查询


mysql> show variables like '%long_query%%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| long_query_time | 10    | 系统需要记录执行时间超过多长的query
+-----------------+-------+


[root@li ~]# vim /usr/local/mysql/etc/my.cnf

log_slow_queries=/var/log/mysqld/mysql55_lamp-slow.log
long_query_time=3

 

 

 

  Query Cache优化
query cache的原理:简单来说就是将客户端请求的query语句(仅限select类型的query)通过一定的hash算法进行一个计算,得到一个hash值,存放在一个hash桶中。同时将该query的结果集(Result Set)也存放在一个内存cache中。存放query hash值的链表中每一个hash值所在节点的同时,还存放了该query所对应的Result Set的Cache所在的内存地址,以及该query涉及的所有table的标识等一些其他相关信息。系统接受到任何一个select类型的query时,首先计算出其hash值,然后通过该hash值到query cache中去匹配,如果找到了完全相同的query,则直接将之前所缓存(cache)Result set返回给客户端,完全不须要进行后面的任何步骤就可完成这次请求。而后端的任何一个表的任何一条数据发生变化之后,也会通知Query cache,须要将所有与该table有关的query的cache全部失效,并释放出之前占用的内存地址,以便后面其他的Query能够使用。
   query cache的负面影响
 1。query语句的hash运算及hash查找资源消耗。虽然hash运算和查找的过程也已经足够的优化了,对于一条query来说消耗的资源确实是非常之少,但是当每秒都有上千甚至几千条query时,就不能对产生的cpu消耗完全忽视了。
 2。query cache的失效问题。如果表的变更比较频繁,则会造成query cache的失效率非常高,表中数据,结构,或索引等的任何变更都会造成将缓存到query cache中的cache数据被清除,导致新的相同query进来后无法使用到之前的cache。
 3。query cache中缓存的是Result Set,而不是数据页,也就是说,存在同一条记录被cache多次的可能性,从而造成内存资源的过渡消耗。

 

   使用query cache
 首先,须判断哪些表适合使用query cache;避免在查询变化频繁的table的query上使用,而应该在那些查询变化频率较低的table的query上使用。mysql中针对query cache有两个专用的SQL Hint(提示):SQL_NO_CACHE和SQL_CACHE,分别代表强制不使用query cache和强制使用query cache.对于那些变化非常少,大部分时候都是静态的数据,可以添加SQL_CACHE的SQL Hint,强制Mysql使用QUERY cache,从而提高该表的查询性能。
 
mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     | mysql是否支持query_cache
| query_cache_limit            | 1048576 | query cache存放的单条query最大Result Set,默认1MB
| query_cache_min_res_unit     | 4096    | 每个result set存放的最小内存大小,默认4KB;
| query_cache_size             | 0       | query_cache_size系统用于query cache内存的大小
| query_cache_type             | ON      | 系统是否打开了query cache功能
| query_cache_wlock_invalidate | OFF     | 针对于MYISAM存储引擎,设置当有WRITE LOCK在某个table上时,读请求是要等write lock释放资源后再查询还是允许从query cache中读取结果,默认为FALSE(可以直接从Query cache中取得结果)


mysql> set global query_cache_size=1024*1024*10;  --设置为10M

 

vim /usr/local/mysql/etc/my.cnf

query_cache_size=10M  --定义query_cache的大小为10M
query_cache_type=1  

/etc/init.d/mysql5  restart

mysql> show variables like '%query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| have_query_cache             | YES      |
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 10485760 |  --再次查看,这里就有10M的大小
| query_cache_type             | ON       |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

 

  获取Query Cache相关的状态变量

mysql> show status like '%Qcache%';

| Variable_name           | Value |
+-------------------------+-------+
| Qcache_free_blocks      | 0     | query cache中目前还有多少多余的blocks。如果该值显示较大,则说明内存碎片过多,要找合适机会整理。
| Qcache_free_memory      | 0     | query cache中目前剩余的内存大小
| Qcache_hits             | 0     | 多少次命中
| Qcache_inserts          | 0     | 多少次未命中然后插入 命中率=Qcache_hits/(Qcache_hits+Qcache_inserts);
| Qcache_lowmem_prunes    | 0     | 多少条query因为内存不足而被清除出query cache
| Qcache_not_cached       | 0     | 因为query_cache_type的设置而不能被缓存cache的query数量,或者是超过了query_cache_limit的单个结果集的设置
| Qcache_queries_in_cache | 0     | 当前query cache中缓存的query数量
| Qcache_total_blocks     | 0     | 当前query cache中的block总数量
+-------------------------+-------+

 

mysql> create table aaa (id int,name varchar(20));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into aaa values('1','sfdasdf');
Query OK, 1 row affected (0.01 sec)

mysql> insert into aaa select * from aaa;

.........

mysql> insert into aaa select * from aaa;
Query OK, 524288 rows affected (5.36 sec)
Records: 524288  Duplicates: 0  Warnings: 0

mysql> show status like '%Qcache%'; --先查看一下状态

mysql> select * from aaa; --这样查看这个一百多W行的大表

mysql> show status like '%Qcache%'; --可以看到并没有cache,Qcache_not_cached增加了,说明应该是结果集超出了范围不能cache

mysql> select * from aaa limit 10; 


mysql> show status like '%Qcache%'; --可以看到 Qcache_inserts 增加1,并且Qcache_queries_in_cache也增加1


mysql> select * from aaa limit 10;  

mysql> show status like '%Qcache%';  --可以看到这次只有Qcache_hits增加1

mysql> select * FROM aaa limit 10;  --这次把from换成大写,结果是一样的,SQL语句的关键字是不区分大小写的

mysql> show status like '%Qcache%';  --可以看到 Qcache_inserts 增加1,并且Qcache_queries_in_cache也增加1;说明语句需要完全一致再能命中query cache


小实验:验证query cache加快查询速度

mysql> set global query_cache_size=1024*1024*100;  --设大点
Query OK, 0 rows affected (0.00 sec)

mysql> set global query_cache_limit=1024*1024*80; --设大点
Query OK, 0 rows affected (0.00 sec)

mysql> show status like '%Qcache%';  --重设过query cache,那么以前缓存的被清0,但命中次数等还是老数据

mysql> select * from aaa; --查100多W行需要1.5秒左右


mysql> show status like '%Qcache%';  --可以看到刚才的语句被缓存,说明把缓存限制调大能存放这100多W行

mysql> select * from aaa;   --现在只需要大概0.25秒左右;说明query cache里取结果是加快了查询速度

mysql> show status like '%Qcache%';  --确认是命中了

 

============================================================

 

 table cache相关的优化
  为了提高性能,在mysql中每个线程都是独立地打开自己需要的表的文件描述符,而不是通过共享已经打开的表的文件描述符的。当然,针对不同的存储引擎可能有不同的处理方式。如myisam表,每一个客户端线程打开任何一个myisam表的数据文件都须要打开一个文件描述符,但如果是索引文件,则可以多个线程共享同一个索引文件的描述符;对于innoDB的存储引擎,如果使用的是共享表空间来存储数据,那么须要打开的文件描述符就比较少,而如果使用的是独享表空间方式来存储数据,由于存储表数据的数据文件较多,则同样会打开很多的表文件描述符。

mysql> show variables like 'table_cache';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| table_cache   | 64    | 当前系统设置的table_cache为64个,也就是说该mysql中,table cache内可以缓存64个打开文件的描述符,但也不是越高越好,设置得太高,可能会造成文件描述符不足,从而造成性能不稳定或者连接失败
+---------------+-------+

mysql> show status like '%open%tables%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Com_show_open_tables   | 0     |
| Open_tables            | 5     |  --当前系统中正打开的描述符有5个,如果在峰值时间open_tables等于table_cache的值,opened_tables也在不断增大,且内存够的情况下要考虑增大table_cache
| Opened_tables          | 0     |

 

mysql> flush table; --此命令会关闭当前table cache中缓存的所有文件描述符
Query OK, 0 rows affected (0.00 sec)

mysql> show status like 'open_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 0     | flush table后,就可以看到正打开的描述符为0了
+---------------+-------+

 


--------------------------------------------------------------
--以下是mysql5.5.X版有关的参数和定义
mysql> show variables like 'table%cache';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| table_definition_cache | 256   | # 表定义缓存,建议比实际的表的数量大
| table_open_cache       | 64    | # 表数据文件描述符号缓存。
+------------------------+-------+

table_open_cache 表数据文件描述符号缓存。
 table_open_cache = max_connections * N ;
  N 代表单个query语句中涉及到的表的数量。
  或者直接把N数值设定为2-3倍。设定大不影响。

 


通过状态数据判断设定是否适当
mysql> show status like 'open%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| Open_files               | 21    | 打开过多少个文件
| Open_streams             | 0     |
| Open_table_definitions   | 15    | 打开过15个表定义文件
| Open_tables              | 9     | 打开过9个表
| Opened_files             | 66    | 
| Opened_table_definitions | 1     | 正在打开一个表定义
| Opened_tables            | 1     | 正在打开一个表
+--------------------------+-------+

 

扩展一个面试题:

 apache使用access_log来记录访问日志


 请问:如果我现在mv access_log access_log.bak后,再来的访问是记录到哪里(apache重启或没有重启分别会是什么情况)

 

------------------------------------------------------------


  mysql server其他常用优化
 网络连接与连接线程
  max_connections 整个MYSQL允许的最大连接数,一般来说500到800左右是一个比较合适的参考值
  
  net_buffer_length 网络包传输中,传输消息之前的net buffer初始化大小
  max_allowed_packet 在网络传输中,一次消息传输量的最大值
  back_log  在MYSQL的连接请求等待队列允许存放的最大连接请求数


max_connections
 mysql最多可以同时连接多少个(并发量),对于那些比较繁忙,并发量比较大的,可以设置500-800。
 lotp 类型(在线事务处理,例如:bbs网站),属于短连接,应该设定大一点
 对于数据仓库,一般连接之后,很久才断开,数据长连接,应该设置少一点

mysql> show status like '%connections%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Connections          | 2     | mysql启动以来接受多少个连接
| Max_used_connections | 1     | 有史以来最大同时连接的峰值
+----------------------+-------+


  thread_cache_size thread cache 池中应该存放的连接线程数,应用程序使用的是短连接,功效最明显,如果是长连接,设置50~100
  thread_stack  每个连接线程被创建时,MYSQL给它分配的内存大小


mysql> show variables like 'thread%';
+-------------------+--------+
| Variable_name     | Value  |
+-------------------+--------+
| thread_cache_size | 50     | 能缓存50个连接数
| thread_stack      | 196608 | 每个连接线程被创建时,mysql给它分配的内存大小
+-------------------+--------+


 连接线程池thread_cache

mysql> show variables like 'thread%';
+-------------------+---------------------------+
| Variable_name     | Value                     |
+-------------------+---------------------------+
| thread_cache_size | 0                         |
| thread_handling   | one-thread-per-connection |
| thread_stack      | 196608                    |
+-------------------+---------------------------+

thread_cache_size  <--连接线程池可以保存多少个空闲线程,0关闭。可以设定一个具体的数值,一般建议50-100.要具体情况设定。
thread_stack  每个线程创建的时候,分配多少的初始化内存给该线程,默认192KB
 


mysql> show status like 'connections';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Connections   | 30    | 系统被连接的次数(注意是次数,不是当前连接数)
+---------------+-------+
1 row in set (0.00 sec)

 

mysql> show status like '%thread%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Delayed_insert_threads | 0     |
| Slow_launch_threads    | 0     |
| Threads_cached         | 3     |  thread cache池中共缓存了3个连接线程
| Threads_connected      | 5     |  当前有5个连接线程处于和客户端连接的状态
| Threads_created        | 8     |  共创建了8个连接线程
| Threads_running        | 1     |  只有一个连接线程正在处理客户端提交的请求
+------------------------+-------+


Sort Buffer,Join Buffer 和 Read Buffer

mysql> show variables like '%buffer%';
+-------------------------------+---------+
| Variable_name                 | Value   |
+-------------------------------+---------+
| bdb_log_buffer_size           | 32768   |
| bulk_insert_buffer_size       | 8388608 |
| innodb_buffer_pool_awe_mem_mb | 0       |
| innodb_buffer_pool_size       | 8388608 |
| innodb_log_buffer_size        | 1048576 |
| join_buffer_size              | 131072  | 只有当join是all,index,rang,或者index_merge时使用到join buffer,这种join被称为Full join.
| key_buffer_size               | 8388600 |
| myisam_sort_buffer_size       | 8388608 | 增大此参数来提高order by或者group by的处理性能,系统默认大小为2MB,最大限制和join buffer一样为
| net_buffer_length             | 16384   | 4G,但在除了windows之外的64位的平台上可以超出4G的限制
| preload_buffer_size           | 32768   |
| read_buffer_size              | 131072  |
| read_rnd_buffer_size          | 262144  |
| sort_buffer_size              | 2097144 | --默认2M,在有大量排序的服务器上可以考虑增大几M
+-------------------------------+---------+

 


============================

二、针对MyISAM的优化
 主要集中于索引的优化。

mysql> show variables like 'key%';
+--------------------------+---------+
| Variable_name            | Value   |
+--------------------------+---------+
| key_buffer_size          | 8384512 |
| key_cache_age_threshold  | 300     |
| key_cache_block_size     | 1024    |
| key_cache_division_limit | 100     |
+--------------------------+---------+

key_buffer_size 默认是8M作为索引缓存区的容量

key_cache_block_size 内存块大小,索引文件是一块一块被mysql缓存。

索引数据的分类:
 热点数据hot sub-chain和普通数据 warm sub-chain

key_cache_division_limit  默认是100,代表不去区别热点数据,直接把key_buffer的所有容量保存普通索引数据缓存。如果是70,那么代表将会使用30%的key_buffer内存空间作为热点数据hot sub-chain保存容量。

key_cache_age_threshold
 数值越小,热点数据更容易被降级为普通数据。


mysql> show status like 'key_%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| Key_blocks_not_flushed | 0     | 
| Key_blocks_unused      | 7245  |
| Key_blocks_used        | 0     |
| Key_read_requests      | 0     |
| Key_reads              | 0     |
| Key_write_requests     | 0     |
| Key_writes             | 0     |
+------------------------+-------+

Key_blocks_not_flushed
 有多少个修改过索引数据块(肮脏数据)还没被刷新到索引文件中。
 注意:如果在对索引文件进行热拷贝,那么该值必须0

Key_blocks_unused 空闲的key_buffer空间

Key_read_requests  key_buffer读请求命中了多少次
Key_reads key_buufer未命中而导致需要从磁盘文件中加载索引数据到内存中
Key_write_requests key_buffer写请求命中了多少次
Key_writes  key_buufer未命中而导致需要从磁盘文件中加载索引数据到内存中才开始对数据进行修改


通过计算命中率,测量设定是否正确:
 读命中率= Key_read_requests/(Key_read_requests+Key_reads)*100
  命中律应该95%以上

 使用百分比=Key_blocks_used/(Key_blocks_used+Key_blocks_unused)
  应该是99-100% 

可以把key_buffer自定义分成多个区域,一般我们自己分,分为:
 hot_area,cold_area,剩下的就是mysql默认存放其他索引数据
 hot_area,cold_area名字是自定义,只不过这里为了声明自定义内存区域的一个典型的用途。


1、设定总的key_buffer容量
mysql> set global key_buffer_size=16*1024*1024;
2、设定关键缓存(自定义区域)
 1)分配6M的空间作为自定义热点数据存放空间
mysql> set global hot_area.key_buffer_size=6*1024*1024;
 
 2)分类2M作为冷数据....
mysql> set global cold_area.key_buffer_size=2*1024*1024;

 说明剩下的8M内存空间作为普通的索引数据缓存空间

3、定义哪些表的索引数据存放哪些区域里。

假设用于存放帖子的pw_threads表,访问热度很高,就应该存放hot_area
mysql> cache index bbs.pw_threads in hot_area;
+----------------+--------------------+----------+----------+
| Table          | Op                 | Msg_type | Msg_text |
+----------------+--------------------+----------+----------+
| bbs.pw_threads | assign_to_keycache | status   | OK       |
+----------------+--------------------+----------+----------+

 

假设pw_help表访问热度很低,但索引数据很庞大,就应该放在cold_area,保证它不根别的索引数据抢空间。

mysql> cache index bbs.pw_help in cold_area;
+-------------+--------------------+----------+----------+
| Table       | Op                 | Msg_type | Msg_text |
+-------------+--------------------+----------+----------+
| bbs.pw_help | assign_to_keycache | status   | OK       |
+-------------+--------------------+----------+----------+

4、根据上面步骤的定义 ,把相应的索引数据进行装载。

mysql> load index into cache bbs.pw_threads,bbs.pw_help ignore leaves;
+----------------+--------------+----------+----------+
| Table          | Op           | Msg_type | Msg_text |
+----------------+--------------+----------+----------+
| bbs.pw_threads | preload_keys | status   | OK       |
| bbs.pw_help    | preload_keys | status   | OK       |
+----------------+--------------+----------+----------+

 

 


===============================================================


mysql AB 复制技术


MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。

同步复制需要使用ndb或者drbd这些技术

 

       打开bin-log  
  master   - slave
  可读可写 一般只可读

 由两个线程  去进行复制的过程   IO线程     sql线程 (以前只使用一个线程,两个是改进后才有的)

复制的过程:
 1,slave端的IO线程连上master端,请求

 2,master端返回给slave端,bin log文件名和位置信息

 3,IO线程把master端的bin log内容依次写到slave端relay log里,并把master端的bin-log文件名和位置记录到master.info里。

 4,salve端的sql线程,检测到relay log中内容更新,就会解析relay log里更新的内容,并执行这些操作;也就是说salve执行和master一样的操作而达到数据同步的目的;

 

   一主一从


关于另几种架构的探讨:

一主多从
   -- salve
  master  -- salve  
   -- salve

--适合于以读为主的业务,使用多个salve分担读的压力,但要注意的是这种架构,savle越多,那么master复制的压力就越大

 

--------------------------------------------
多主一从     --这种架构不支持

--------------------------------------------


双主架构        master   -- master

master端如果要进行特别的维护,要停库;为了减少写等待的时间可能会要求把slave转为master库来进行写

等主库开服务后,slave库写的操作不能复制到master库,数据不一致,那这种情况,就必须重做复制架构

所以使用master-master架构,互相复制


他们不会循环复制,因为做复制时会指定ID值,并且不一致

  但是master-master架构,如果两台都同读同写的话,也会造成数据不一致


  时间点  master A master B
    1  a=1改为a=2
    2    a=1改为a=3
    3    a的改变复制过来,并解析,a会又改为2
    4  b的改变复制过来并解析,a又会改为3 
 
  问题产生,数据不一致

可能通过一些特殊的参数,指定一些表的写操作全在一端,另一些表的写操作全在另一端,也就是说两边不会同时写相同的表,就可以避免上面的问题了


另一种情况避免就是说一般也只把一台进行写操作,另一台只有在写操作的那台停服务时才进行写

 

-------------------------------------------------

      -- salve
级联架构  master -- salve -- salve
      -- salve


 
 为了解决一主多从的master的复制压力
 可以把slave做为下一级从机的master

 增加复制的级联层次,造成的延迟更长

 所以这种架构并不是很推荐,一般会进行分拆集群


-----------------------------------------
     master
     |      | 
环型架构   master  -- master  

--不可行


----------------------------------------------

双主和级联合起来


   master
      |
     |      -- slave
   master ---salve -- slave
         -- slave


=========================================================


-------------------------------------------------------------

搭建环境  两台虚拟机

  master -- slave
         2.2.2.36    2.2.2.37  

 

这里选择使用5.5.13版源码版

1,先两边编译安装mysql  


/share/soft/lamp/mysql_source/cmake-2.8.4.tar.gz
/share/soft/lamp/mysql_source/mysql-5.5.13.tar.gz


解压后

# cd /usr/src/cmake-2.8.4/
# ./configure ; make ;make install

# cd /usr/src/mysql-5.5.13/
# cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DDEFAULT_CHARSET=gbk -DDEFAULT_COLLATION=gbk_chinese_ci -DWITH_EXTRA_CHARSETS=utf8,gb2312 -DENABLED_LOCAL_INFILE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1

# make ;make install

手动编写my.cnf配置文件
[root@li /]# mkdir /usr/local/mysql/etc
[root@li /]# vim /usr/local/mysql/etc/my.cnf

[mysqld]
port=3306
basedir=/usr/local/mysql
datadir=/data
pid-file=/var/run/mysqld/mysql55.pid
socket=/var/run/mysqld/mysql55.socket
log-error=/var/log/mysqld/mysql55-err.log
user=mysql

[client]
socket=/var/run/mysqld/mysql55.socket


创建相关目录,并修改权限
[root@li /]# groupadd -g 27 mysql
[root@li /]# useradd -u 27 -g mysql mysql

[root@li /]# mkdir /data /var/run/mysqld /var/log/mysqld
[root@li /]# chown mysql.mysql /data /var/run/mysqld /var/log/mysqld /usr/local/mysql/   -R

初始化数据库
# /usr/local/mysql/scripts/mysql_install_db --defaults-file=/usr/local/mysql/etc/my.cnf --basedir=/usr/local/mysql  --user=mysql


拷贝服务脚本
[root@li ~]# cp /usr/src/mysql-5.5.13/support-files/mysql.server /etc/init.d/mysql55

[root@li ~]# chmod 755 /etc/init.d/mysql55

[root@li ~]# vim /etc/init.d/mysql55
 conf=/usr/local/mysql/etc/my.cnf  --修改这一句


启动服务
[root@li ~]# /etc/init.d/mysql55 start --直接脚本启动

 

====================================

AB复制前准备
把两台mysql启起来(要求两台数据一致),/etc/hosts里都加上主机名和IP对应,时间同步好,防火墙检查一下

 


mysql AB复制开始搭建
1,主从数据必须要同步
2,主:要启用二进制日志   /usr/local/mysql/etc/my.cnf       log-bin=xxxxx
3,主和从都要设置 server-id值,并且两边要不一样
4,需要建立一个用来复制的用户,并授于相应权限


   master -- slave
         2.2.2.36    2.2.2.37  

 

 

第一步;改配置文件

master的
[mysqld]
log-bin=mysql-bin
server-id=2

slave的
 [mysqld]
 server-id=3

/etc/init.d/mysql5  重启服务

 


第二步:授权


master上授权,super和replication slave都是复制要用的权限
mysql> grant super,replication slave on *.* to 'li'@'2.2.2.37' identified by '123';
mysql> flush privileges;


slave上最好使用刚才授权的用户是远程登录一下主
[root@slave src]# /usr/local/mysql/bin/mysql -u li -h 2.2.2.36 -p123
ERROR 1130 (HY000): Host '::ffff:2.2.2.36' is not allowed to connect to this MySQL server
--上面是IPV6所造成的影响,所以要去主上面重新授权


master上重新授权,写上IPv6的形式,或者使用%符号代替所以(但不建设这样做,这样就没有对slave做权限控制)
mysql> grant super,replication slave on *.* to 'li'@'::ffff:2.2.2.36' identified by '123';
mysql> flush privileges;

再验证一下,发现登陆OK


第三步:查看master的正在写的二进制文件名和位置
mysql> flush tables with read lock;  --先加锁,防止两边数据不一致
Query OK, 0 rows affected (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      681 |              |                  |
+------------------+----------+--------------+------------------+

二进制文件名  正在写入的位置


slave端量的配置
mysql> slave stop;
Query OK, 0 rows affected, 1 warning (0.00 sec)


mysql> change master to
    -> master_user='li',
    -> master_password='123',
    -> master_host='2.2.2.36',  --主的IP
    -> master_port=3306,   --端口,如果为3307就要换成3307
    -> master_log_file='mysql-bin.000001', --主上面查到的文件名
    -> master_log_pos=681;   --主上面查到的位置号

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)


mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 2.2.2.36
                  Master_User: li
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 681
               Relay_Log_File: mysql55-relay-bin.000002
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes   --这里两个YES,表示两个线程OK
              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: 681
              Relay_Log_Space: 411
              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:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 2
1 row in set (0.00 sec)

...................................

回到master端解锁:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)


进行测试:

1,先比较主,从的数据目录文件的不同

[root@master ~]# ls /data/ --主的
ibdata1      mysql             performance_schema
ib_logfile0  mysql-bin.000001  test
ib_logfile1  mysql-bin.index


[root@slave ~]# ls /data/ --从的
ibdata1                   mysql55-relay-bin.000002
ib_logfile0               mysql55-relay-bin.index
ib_logfile1               performance_schema
master.info               relay-log.info
mysql                     test
mysql55-relay-bin.000001

 

验证2:只有master写,slave可以看到
 slave写,master看不到

如果复制有问题,删除slave端/data/master.info再做


验证3:把从重启后,再上去查看状态,还是连接的,没什么影响

 把主重启后,再去slave上去查看状态,发现重试时间为60秒,等60秒后又自动连接OK了

 

=================================


------------------------------------------------------------

一主多从的做法


 就是上面的步骤有几个从就做几次

 

------------------------------------------------------------------------


双主架构的做法:

 在上面的slave机也打开二进制日志,反着做一遍就行,注意做的过程中,保证数据一致

 

--------------------------------------------------------------


级联架构      

  master -slave -slave

 

把中间的从也要打开二进制日志。但是它默认不把应用master的操作记录到自己的二进制日志。所以需要打开一个参数让它记录,才可以传给第三级的从


# /usr/local/mysql/bin/mysqld --verbo --help |grep log-slave

  --log-slave-updates Tells the slave to log the updates from the slave thread
                      --log-slave-updates is used.
log-slave-updates                                 FALSE

--默认值为false,所以需要在配置文件里加上log-slave-updates=1,然后重启服务

所以打开中间从的配置文件
# vim /usr/local/mysql/etc/my.cnf  --加上下面两句,然后重启服务
log-bin=mid-slave
log-slave-updates=1 

 

然后在中间从和第三级的从之间再做一次AB复制就可以了

 

我的结构图


  master     slave         slave

2.2.2.36     2.2.2.37        2.2.2.35  

sever-id=2    server-id=3        server-id=4
log-bin=master    log-bin=mid-slave 
     log-slave-updates=1


===============================

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章