1: 首先確定Master和Slave的數據庫版本,Master數據庫的版本不能高于Slave數據的版本。
這里我是使用MySql 5.0.27 作為Master數據庫,MySql 6.0.3(alpha)作為Slave進行測試。
2:首先修改Master數據庫的配置文件my.ini (windows), /etc/my.cnf(linux)里
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
bind-address=173.45.243.171 #master server ipadreess
port=3306
set-variable = connect_timeout=10
set-variable = key_buffer_size=50M
set-variable = thread_cache_size=950
set-variable = table_cache=4200
set-variable = max_connect_errors=999999999
set-variable = max_connections=800
set-variable = tmp_table_size=10M
set-variable = wait_timeout=120
set-variable = max_write_lock_count=120
set-variable = query_cache_type=1
set-variable = query_cache_size=50M
log-slow-queries
memlock
skip-innodb
skip-locking
skip-name-resolve
# Try number of CPU's*2 for thread_concurrency
thread_concurrency=16
#########################
# start master settings #
#########################
#binlog-do-db=database
#binlog-ignore-db=db_name
set-variable = max_binlog_size=10M
log-bin=/var/log/mysql/mysqlbinlog/pts1-log-bin //使用的二進制日志文件名
log-bin-index=/var/log/mysql/mysqlbinlog/pts1-log-bin.index
server-id=1 //服務器編號
#######################
# end master settings #
#######################
[mysql.server]
user=mysql
[mysqld_safe]
log-error=/var/log/mysql/mysqld.log
pid-file=/var/log/mysql/mysqld.pid
在Slave數據庫的配置文件my.ini, or my.cnf里添加server-id 項
eg:[mysqld]
server-id = 2
(這里需要理解的是Slave本身也是一個獨立的服務器,它作為‘從數據庫’是從它通過‘主服務器’日志更新數據角度上理解的。可以把 server-id
想象成為IP地址:這些ID標識了整個同步組合中的每個服務器。如果沒有指定 server-id
的值,如果也沒定義 master-host
,那么它的值就為1,否則為2。注意,如果沒有設定 server-id
,那么master就會拒絕所有的slave連接,同時slave也會拒絕連接到master上。)
整個修改如下:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
bind-address=173.45.243.96 #slave server ipadreess
port=3306
set-variable = connect_timeout=10
set-variable = key_buffer_size=50M
set-variable = thread_cache_size=950
set-variable = table_cache=4200
set-variable = max_connect_errors=999999999
set-variable = max_connections=800
set-variable = tmp_table_size=10M
set-variable = wait_timeout=120
set-variable = max_write_lock_count=120
set-variable = query_cache_type=1
set-variable = query_cache_size=50M
log-slow-queries
memlock
skip-innodb
skip-locking
skip-name-resolve
# Try number of CPU's*2 for thread_concurrency
thread_concurrency=16
#########################
# start master settings #
#########################
#set-variable = max_binlog_size=10M
#log-bin=/var/log/mysql/mysqlbinlog/pts2-log-bin
#log-bin-index=/var/log/mysql/mysqlbinlog/pts2.index
#server-id=1
#######################
# end master settings #
#######################
#########################
# start slave settings #
#########################
relay-log-space-limit=50M
set-variable = max-relay-log-size=10M
set-variable = report-host=173.45.243.96:3306
master-host=173.45.243.171
master-user=repl
master-password=repl12
master-port=3306
master-connect-retry=60
server-id=1562
#replicate-do-db=test #let slave only do test db's update
#######################
# end slave settings #
#######################
[mysql.server]
user=mysql
[mysqld_safe]
log-error=/var/log/mysql/mysqld.log
pid-file=/var/log/mysql/mysqld.pid
3:修改配置后啟動Master數據服務。在Master數據庫上建立一個用戶,用于Slave數據連接以便同步數據。一般來說Slave數據只用于同步數據,所以我們在建立這個用戶時只授予它REPLICATION SLAVE 權限。
eg: GRANT REPLICATION SLAVE ON *.* TO 'repl'@173.45.243.96 IDENTIFIED BY ‘repl12’;
4:在Master數據庫上執行 FLUSH TABLES WITH READ LOCK; 命令以刷新數據并阻止對Master數據的寫入操作。然后將Master數據的data目錄復制一份覆蓋Slave數據庫的data目錄,這樣Master和Slaver就有了相同的數據庫了。在復制時可能不需要同步 mysql 數據庫,因為在slave上的權限表和master不一樣。這時,復制的時候要排除它。同時不能包含任何`master.info~ 或 `relay-log.info` 文件。覆蓋好后執行 UNLOCK TABLES; 釋放鎖定。
5:在Master數據庫上執行SHOW MASTER STATUS; 查看當前Master數據庫上的一些我們將要使用的信息:
File 表示 Master用于記錄更新數據操作的日志文件,Position 表示當前日志的記錄位置,這也是Slave 需要開始同步數據的位置。
6:啟動Slave數據庫 執行:(這點連接Master數據庫所要的參數)
mysql> stop slave;
mysql> CHANGE MASTER TO
-> MASTER_HOST='173.45.243.171', //Master服務器地址(if是在本機上安裝兩個數據庫的, 則用127.0.0.1)
-> 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操作線程已經成功啟動。
eg:
mysql> show slave status;
+----------------------------------+----------------+-------------+-------------+---------------+---------------------+---------------------+-------------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Slave_IO_State | Master_Host | Master_User | Master_Port | Connect_Retry | Master_Log_File | Read_Master_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Master_Log_File | Slave_IO_Running | Slave_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Master_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Master_SSL_Allowed | Master_SSL_CA_File | Master_SSL_CA_Path | Master_SSL_Cert | Master_SSL_Cipher | Master_SSL_Key | Seconds_Behind_Master |
+----------------------------------+----------------+-------------+-------------+---------------+---------------------+---------------------+-------------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Waiting for master to send event | 173.45.243.171 | root | 3306 | 60 | pts1-log-bin.000005 | 839 | mysqld-relay-bin.000005 | 979 | pts1-log-bin.000005 | Yes | Yes | | | | | | | 0 | | 0 | 839 | 979 | None | | 0 | No | | | | | | 0 |
+----------------------------------+----------------+-------------+-------------+---------------+---------------------+---------------------+-------------------------+---------------+-----------------------+------------------+-------------------+-----------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
1 row in set (0.00 sec)
一般情況下,重新啟動SLAVE的MYSQL就可以了。
如果Slave-IO-Running=No, 重新啟動MASTER和SLAVE的MYSQL再試一下。
7:到此已經建立Master和Slave數據庫的同步了。你可以在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
|
(測試數據統計表)
雖然數據測試是很粗糙的,但確實反映出性能的一定改善。
posted on 2009-02-12 15:51
Blog of JoJo 閱讀(750)
評論(2) 編輯 收藏 所屬分類:
Linux 技術相關