在MySql上实现Replication(Master 与 Slave 数据同步) 一

 



1 首先确定MasterSlave的数据库版本,Master数据库的版本不能高于Slave数据的版本。

这里我是使用MySql 5.0.27 作为Master数据库,MySql 6.0.3alpha)作为Slave进行测试。

 

2:首先在Master数据库的配置文件my.ini (windows)里添加log-bin server-id 两项

  eg: [mysqld]

     log-bin = mysql-bin  //使用的二进制日志文件名

     server-id = 1  //服务器编号

   Slave数据库的配置文件my.ini里添加server-id

   eg:[mysqld]

        server-id = 2

(这里需要理解的是Slave本身也是一个独立的服务器,它作为‘从数据库’是从它通过‘主服务器’日志更新数据角度上理解的。可以把 server-id 想象成为IP地址:这些ID标识了整个同步组合中的每个服务器。如果没有指定 server-id 的值,如果也没定义 master-host,那么它的值就为1,否则为2。注意,如果没有设定 server-id,那么master就会拒绝所有的slave连接,同时slave也会拒绝连接到master上。)

 

3:修改配置后启动Master数据服务。在Master数据库上建立一个用户,用于Slave数据连接以便同步数据。一般来说Slave数据只用于同步数据,所以我们在建立这个用户时只授予它REPLICATION SLAVE 权限。

  eg: GRANT REPLICATION SLAVE ON *.* TO ‘slaver’@’%’ IDENTIFIED BY ‘slaver’;

 

4:在Master数据库上执行 FLUSH TABLES WITH READ LOCK; 命令以刷新数据并阻止对Master数据的写入操作。然后将Master数据的data目录复制一份覆盖Slave数据库的data目录,这样MasterSlaver就有了相同的数据库了。在复制时可能不需要同步 mysql 数据库,因为在slave上的权限表和master不一样。这时,复制的时候要排除它。同时不能包含任何`master.info~ `relay-log.info` 文件。覆盖好后执行 UNLOCK TABLES; 释放锁定。

 

5:在Master数据库上执行SHOW MASTER STATUS; 查看当前Master数据库上的一些我们将要使用的信息:

 

File 表示 Master用于记录更新数据操作的日志文件,Position 表示当前日志的记录位置,这也是Slave 需要开始同步数据的位置。

 

6:启动Slave数据库 执行:(这点连接Master数据库所要的参数)

mysql> CHANGE MASTER TO

    ->  MASTER_HOST='127.0.0.1',  //Master服务器地址(我是在本机上安装两个数据库的)

    ->  MASTER_USER='slaver,  //Slave服务器更新时连接Master使用的用户名

    ->  MASTER_PASSWORD='slaver',  // Slave服务器更新时连接Master使用的密码

    ->  MASTER_LOG_FILE='mysql-bin.000004', //更新操作日志

    ->  MASTER_LOG_POS=837016;   //同步数据的开始位置

 

上面命令执行完毕后,执行START SLAVE; 命令启动数据更新。在Slave 数据库上执行:

SHOW SLAVE STATUS; 查看从数据跟主数据库的连接状态是否正常,如果显示的信息中

Slave-IO-Running Slave_SQL_Running 值为 yes,表示用于数据同步的 io线程和sql操作线程已经成功启动。

 

7:到此已经建立MasterSlave数据库的同步了。你可以在Master数据库上更新一个表的数据,然后查看Slave数据库上对应表是否做了相应的更改。

注: slave开始同步后,就能在数据文件目录下找到2个文件 `master.info` `relay-log.info`slave利用这2个文件来跟踪处理了多少master的二进制日志。master.info 记录了slave 连接master进行数据同步的参数,relay-log.info 记录了slave进行数据更新使用的中续日志的的信息。

Master 与 Slave 数据同步后对性能进行粗略的测试:

(1). 在Master数据库上建立一个新的数据库testdata,并建立表testdata。建立脚本如下

CREATE   DATABASE  `testdata`  /*!40100 DEFAULT CHARACTER SET utf8 */ ;

DROP   TABLE   IF   EXISTS  `testdata`.`testms`;
CREATE   TABLE   `testdata`.`testms` (
  `name` 
text   NOT   NULL
) ENGINE
= InnoDB  DEFAULT  CHARSET = utf8;
注意:由于上面我们建立的Master和Slave之间的数据同步是针对所有数据库的,所以当你在Master上建立数据库和表后,Slave 上自动也会建立对应的数据库和表,如果发现Slave上没有对应的数据库和表则必须检查是否Master和Slave是否正常同步数据。

 

(2). 测试代码如下(Java):

分别调用两个不同的方法,进行两种类型的测试



package  com.ckcs.test;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 
*/


import  java.sql.Connection;
import  java.sql.DriverManager;
import  java.sql.SQLException;
import  java.sql.Statement;
import  java.util.logging.Level;
import  java.util.logging.Logger;

/**
 *
 * 
@author Administrator
 
*/

public   class  TestMS  {

    
/**
     * 对master数据库进行数据插入和查询操作
     
*/

    
private void testSingleDB() {
        
try {
            
//Master数据库
            final String singleUrl = "jdbc:mysql://localhost:3306/testdata?characterEncoding=utf-8&user=super&password=iamasuper006";
            Class.forName(
"com.mysql.jdbc.Driver");
            
new Thread() {

                
public void run() {
                    
long start = System.currentTimeMillis();
                    
try {
                        Connection updateCon 
= DriverManager.getConnection(singleUrl);
                        
for (int i = 0; i < 1000; i++{
                            Statement state 
= updateCon.createStatement();
                            
//插入数据
                            state.execute("insert into testms values('wo de tian kong.')");
                            state.close();
                        }

                    }
 catch (SQLException ex) {
                        Logger.getLogger(TestMS.
class.getName()).log(Level.SEVERE, null, ex);
                    }

                    System.out.println(
"更新用时: " + (System.currentTimeMillis() - start));
                }

            }
.start();
            
new Thread() {

                
public void run() {
                    
long start = System.currentTimeMillis();
                    
try {
                        Connection queryCon 
= DriverManager.getConnection(singleUrl);
                        
for (int j = 0; j < 100000; j++{
                            Statement queryState 
= queryCon.createStatement();
                            
//查询数据
                            queryState.execute("select * from testms");
                            queryState.close();
                        }

                    }
 catch (SQLException ex) {
                        Logger.getLogger(TestMS.
class.getName()).log(Level.SEVERE, null, ex);
                    }

                    System.out.println(
"查询用时: " + (System.currentTimeMillis() - start));
                }

            }
.start();


        }
 catch (Exception ex) {
            Logger.getLogger(TestMS.
class.getName()).log(Level.SEVERE, null, ex);
        }

    }


    
/**
     * 对Master数据库进行数据的插入,对Slave数据库进行数据的查询
     
*/

    
private void testMSDB() {
        
try {
            
//Master 数据库
            final String updateUrl = "jdbc:mysql://localhost:3306/testdata?characterEncoding=utf-8&user=super&password=iamasuper006";
            Class.forName(
"com.mysql.jdbc.Driver");
            
new Thread() {

                
public void run() {
                    
long start = System.currentTimeMillis();
                    
try {
                        Connection updateCon 
= DriverManager.getConnection(updateUrl);
                        
for (int i = 0; i < 1000; i++{
                            Statement updateState 
= updateCon.createStatement();
                            
//插入数据
                            updateState.execute("insert into testms values('wo de tian kong.')");
                            updateState.close();
                        }

                    }
 catch (SQLException ex) {
                        Logger.getLogger(TestMS.
class.getName()).log(Level.SEVERE, null, ex);
                    }

                    System.out.println(
"更新用时: " + (System.currentTimeMillis() - start));
                }

            }
.start();
            
//Slave数据库
            final String queryUrl = "jdbc:mysql://localhost:3307/testdata?characterEncoding=utf-8&user=super&password=iamasuper006";
            
new Thread() {

                
public void run() {
                    
long start = System.currentTimeMillis();
                    
try {
                        Connection queryCon 
= DriverManager.getConnection(queryUrl);
                        
for (int j = 0; j < 100000; j++{
                            Statement queryState 
= queryCon.createStatement();
                            
//查询数据
                            queryState.execute("select * from testms");
                            queryState.close();
                        }

                    }
 catch (SQLException ex) {
                        Logger.getLogger(TestMS.
class.getName()).log(Level.SEVERE, null, ex);
                    }

                    System.out.println(
"查询用时: " + (System.currentTimeMillis() - start));
                }

            }
.start();
        }
 catch (Exception ex) {
            Logger.getLogger(TestMS.
class.getName()).log(Level.SEVERE, null, ex);
        }

    }


    
public static void main(String[] args) {
        TestMS test 
= new TestMS();
        test.testMSDB();
    }

}

 

(3).测试所得数据:

1)测试数据比较

注: 查询数据次数为 100000; 插入数据次数为1000

              测试

类型

测试次数

用时

  Master数据库进行插入和查询操作

Master数据库进行插入操作,对Slave数据库进行查询操作

 插入

查询

  插入

 查询

  第一次用时

63141

18172

66078

10656

  第二次用时

67875

20109

68969

11860

  第三次用时

65796

18265

65672

10906

  平均用时

65604

18848

66906

11140

                                      (测试数据统计表)

虽然数据测试是很粗糙的,但确实反映出性能的一定改善。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值