mysql主從複製案例及小結

mysqlAB複製
mysql主從複製有利於數據庫的健壯性、提高訪問速度和易於維護管理。
總結:
從庫上配置帳戶、ip、用戶名、密碼、連接文件的位置、pos點,在從庫上同步數據前要把主庫以前的數據導入到從庫,而後在實行數據同步。
開啓開關以前,主從庫數據要一致
在打開開關以前要在主庫上創建受權,連接從庫的帳號
主庫必需要打開bin-log開關
要啓動 start slave;來開始同步
dns主-----> dns從   非實時

mysql主------------------> mysql從    實時
    延時是很嚴重的問題


mysql replication
     
mysql AB 複製技術(主從)    原理很是相似 oracle dataguard oracle DG (dataguard)

MySQL支持單向、異步複製,複製過程當中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。

同步複製須要使用ndb(各集羣節點均可讀可寫)或者drbd(網絡raid)這些技術,或者是新版mysql的半同步複製


異步        優勢:主速度快  缺點:數據可能主從不一樣步
同步        優勢和缺點和異步正好相反



            mysql主  ---------->   mysql從

            create table aaa;
            bin-log   -------->   relay-bin-log
                               io            
                        sql create table aaa;



把主上的二進制日誌(bin-log)的內容傳到從上的一個新的日誌叫relay-bin-log
        從上的    IO 線程  負責傳輸        
        從上的    SQL 線程  負責從服務器解析日誌



    由兩個線程  去進行復制的過程   IO線程     sql線程    (之前只使用一個線程,兩個是改進後纔有的)



複製的過程:
    1,slave端的IO線程連上master端,請求

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

    3,IO線程把master端的bin log內容依次寫到slave端relay bin log裏,並把master端的bin-log文件名和位置記錄到master.info裏。

    4,salve端的sql線程,檢測到relay bin log中內容更新,就會解析relay log裏更新的內容,並執行這些操做;也就是說salve執行和master同樣的操做而達到數據同步的目的;



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


AB複製前準備
1,準備兩臺機器
2,安裝兩臺全新的mysql(這裏使用rpm版,方便,源碼版能夠課後自行作測試;兩臺版本最好一致,不一致可能會有兼容性問題) yum -y install mysql*
3,主機名配置及其綁定(兩臺互相綁定)
vim /etc/hosts  (主機名和ip相互綁定只綁本身的)
4,時間同步
5,防火牆,selinux關閉

準備兩臺虛擬機:最好是全新
      master    ----        slave
            172.16.14.2              172.16.14.3


第一步;改配置文件,並重啓服務
# vim /etc/my.cnf    
master上   (主文件)
[mysqld] 
log-bin=mysql-bin     二進制日誌必須打開
server-id=2

slave上   (副文件)
[mysqld]
server-id=3

/etc/init.d/mysqld restart   用腳本重啓


    

第二步:主受權 在主文名字是主到  ip寫從到
master上受權,super和replication slave都是複製要用的權限
mysql> grant super,replication slave on *.* to 'li'@'172.16.14.X' identified by '123';    在主受權給從的ip地址,讓他以主到身份登陸  li表明的是主機名
mysql> flush privileges;


第三步:查看master的正在寫的二進制文件名和位置
mysql> show master status;    --只有打開二進制日誌,這句命令纔有結果,表示當前數據庫的二進制日誌寫到什麼位置
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      473 |              |                  |
+------------------+----------+--------------+------------------+


第四步:在slave(從)上鍊接master(主),並指定從哪一個position開始複製
在(從端操做)下面
mysql> change master to
    -> master_user='li',            --對應前面主受權時的用戶
    -> master_password='123',            --對應前面主受權時的密碼
    -> master_host='172.16.14.2',        --主的IP
    -> master_port=3306,            --端口,若是爲3307就要換成3307
    -> master_log_file='mysql-bin.000003',    --主上面查到的文件名
    -> master_log_pos=473;            --主上面查到的位置號
這部報錯的話把stop slave;  切記必須關掉以後在修改,而後啓動

mysql> start slave;
mysql> show slave status\G 查看錶
......
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes    --這兩人個線程爲yes,表明集羣搭建成功
......

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

問題一:
思考幾種狀況下作複製的區別:
1, 業務尚未上線的狀況,全新安裝的mysql作複製
2,主已經跑了一年,一直都有開着二進制日誌,而且日誌無丟失
直接從一年前的起始位置開始複製(但要注意初始化的數據不要重複初始化的數據)
3,主已經跑了一年,但沒有打開二進制日誌
驟一:master打開二進制日誌,重啓
步驟二:master全備,並恢復到slave(假設要30分鐘)
步驟三;30分鐘後,slave從備份的position開始複製
4, 主之前跑了半年沒打開二進制日誌,後半年打開了二進制日誌,你如今要作從
驟一:master全備,並恢復到slave(假設要30分鐘)
步驟二;30分鐘後,slave從備份的position開始複製
            主        從

            .000001    1    
             跑了一年        跑了一年的數據
如今            .000054   563    563
              備份恢復 30分鐘
            
            .000054   800     



問題二:
主要打開二進制日誌,從要不要開二進制日誌?
從mysql可開可不開,要看狀況


問題三:
主和從的讀寫狀況怎麼作?
從不能寫,從只能讀;主可讀可寫;
因此有些時候作主只寫,從只讀,也就是讀寫分離


問題四:
我作了讀寫分離的一主一從的架構,請問我前端的程序(web,遊戲,業務等)如何來訪問數據庫?

若是裝前端web(假設phpwind),填寫數據庫的IP爲主的IP,那麼這種狀況,
mysql從就徹底變成了一個實時備份的服務器,全部的讀寫全在主上
因此要在前端程序和數據庫之間加入代理層程序,也就是填寫的數據庫IP不是主的也不是從的,
而是代理的,由代理來負責把寫操做給主,讀操做給從


                客戶    
                |
                |    
         web程序,遊戲程序(c,php,java.......)    
                |
                |
             代理層(中間件)(mysqlproxy,amoeba,cobar,mycat)        
                |    
                |    
        mysql主   ---->     mysql從



問題五:
關於單點故障的問題,若是從掛掉了,怎麼解決?若是主掛掉了,怎麼解決?

從掛掉,再恢復的過程圖:

              代理

        mysql主   ---->     mysql從
         寫          讀
                 從掛了        
         寫讀
                好久以後,從要啓動,啓動以前能夠手動寫防火牆,讓代理訪問不到從
                啓動,會自動連主,主會把這段時間寫的複製給從
                複製完後,手動確認(能夠在從啓動前在主上show master status;查看主寫到哪了.而後在從上能夠show slave status查看寫到主的postion或者這個positsion以後,則表示數據都複製過來了),而後去掉防火牆
                代理髮現從OK了,會把讀給從
        寫        讀


主掛掉,再恢復的過程圖:(這樣最好作雙主,右邊的主平時正常狀況而後作只讀的從,只在左邊的主掛了,纔會作寫操做)

               代理

        mysql主   <---->   mysql從(打開二進制日誌)
        寫          讀
        主掛了
                 寫 讀
       好久以後,主要啓動,啓動以前手動寫防火牆,讓代理訪問不到主
      主啓動,自動連上後,由於是雙主,從能夠把這段時間寫的複製回主
        複製完後,手動確認,而後去掉主上的防火牆
        代理髮現主OK了,會把寫給回主
        寫         讀


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

一主一從

關於另幾種架構的探討:

一主多從
            --    salve
        master  --    salve        
            --    salve


--適合於以讀爲主的業務,使用多個salve分擔讀的壓力,但要注意的是這種架構,salve越多,那麼master複製的壓力就越大(成本增大)

多主一從     --這種架構不支持


        主A phpwind
                    從C
        主B discuz        

雙主架構           master A  <-->   master B  
        phpwind主      discuz主    



上面已經討論了雙主架構的一個用法(就是一個平時仍然爲主,另外一個平時爲從,只在主掛了纔會去從上寫)


1,會循環複製嗎?
他們不會循環複製,由於作複製時會指定ID值,而且不一致


2,兩邊真的能同時寫相同的數據嗎?
可能會有問題

以下表所示:

時間點        master    A    master    B
1        id=1改成id=2
2                id=1改成id=3
3                master A的改變複製過來,並解析,id會又改成2
4        master B的改變複製過來並解析,id又會改成3    
    
        問題產生,數據不一致



3,兩邊能夠寫不一樣的數據嗎?

能夠
能夠經過業務程序層,指定一些表的寫操做全在一端,另外一些表的寫操做全在另外一端,也就是說兩邊不會同時寫相同的表(固然這是理想狀態,由於業務複雜的話會有表的聯結等狀況)
而後經過指定mysql複製的參數,一部分表或庫會從A複製到B,另一部分表或庫從B複製到A就能夠避免上面的問題了

或者兩個庫,一個庫master A來寫,另外一個庫master B來寫

數據切分


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

                master C
                |      |    
環型架構            master A -- master B    


--不可行

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



                    --    salve
級聯架構        master    --    salve    --    salve
                    --    salve



    爲了解決一主多從的master的複製壓力
    能夠把slave作爲下一級從機的master

    增長複製的級聯層次,形成的延遲更長

    因此這種架構並非很推薦,通常會進行分拆集羣


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


雙主和級聯合起來


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


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


優化原則:分


大型結構的數據量太大,要用到數據切分(水平,垂直)

mysqlproxy 
amoeba
cobar


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

一主多從的作法


    就是上面的步驟有幾個從就作幾回



雙主架構的作法:

    反着作一遍就行


級聯架構               
    
    master -slave -slave


個人結構圖


  master A          slave B                         slave C

172.16.14.2          172.16.14.3                  172.16.14.4        

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


bin-log                 relay-bin-log                 relay-bin-log


bin-log    ------>       relay-bin-log
        打開log-slave-updates=1
        讓第一臺傳過來relay日誌記錄
        到本身的二進制日誌
           bin-log  ------->    relay-bin-log  

 
練習:
實現下面的結構圖(這裏包括了一主一從,一主多從,雙主,級聯架構)
mysql1 《----》  mysql2    ----》 mysql3

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

半同步複製


MySQL的默認複製實際上是異步操做,而不是同步,也就意味着容許主從之間的數據存在一
定的延遲,mysql當初這樣設計的目的也是基於可用性的考慮,爲了保證master
不受slave的影響,而且異步複製使得master處於一種性能最優的狀態:

寫完binlog後便可提交而不須要等待slave的操做完成。這樣存在一個隱患,當你使用slave做爲備份時

若是master掛掉,那麼會存在部分已提交的事務未能成功傳輸到slave的可能,這就意味着數據丟失!


        mysql 主 ---- mysql從


所謂的半同步複製就是master每commit一個事務,要slave應用這個事物後回給master信號。這樣master才能把事物成功commit。這樣就保證了master-slave的數據絕對的一致(可是以犧牲master的性能爲代價).但等待時間也是能夠調整的。
mysql半同步複製等待時間超時後(默認時間爲10秒),會自動轉換成異步複製



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

搭建環境  兩臺虛擬機

        master    --    slave
                    


先安裝mysql5.5以後的版本,由於這個版本以後才實現的半同步複製


第一大步:
先要搭建好mysqlAB異步複製

過程省略


第二大步:在異步基礎上轉成半同步複製

1,在master上安裝這個插件

master> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.00 sec)

--刪除插件的方法 mysql > uninstall plugin rpl_semi_sync_master;


master> show global variables like 'rpl_semi_sync%';  --安裝OK後,主上會多幾個參數
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | OFF   |    --是否啓用master的半同步複製
| rpl_semi_sync_master_timeout       | 10000 |  --默認主等待從返回信息的超時間時間,10秒。
| rpl_semi_sync_master_trace_level   | 32    |  --監控 
| rpl_semi_sync_master_wait_no_slave | ON    |    --是否容許每一個事物的提交都要等待slave的信號.on爲每個事物都等待
+------------------------------------+-------+



2,在slave上安裝插件
slave> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.03 sec)


slave>  show global variables like 'rpl_semi_sync%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+


3,master上激活半同步複製
master> set global rpl_semi_sync_master_enabled =on;
Query OK, 0 rows affected (0.00 sec)


4,slave上激活半同步複製
slave> set global rpl_semi_sync_slave_enabled=on;
slave> stop slave IO_THREAD;
slave> start slave IO_THREAD;




5,在master查看狀態
master > show global status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |    --有一個從服務器啓用半同步複製
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |    --master等待slave回覆的平均等待時間。單位毫秒
| Rpl_semi_sync_master_net_wait_time         | 0     |    --master總的等待時間。單位毫秒
| Rpl_semi_sync_master_net_waits             | 0     |    --master等待slave回覆的總的等待次數
| Rpl_semi_sync_master_no_times              | 0     |  --master關閉半同步複製的次數
| Rpl_semi_sync_master_no_tx                 | 0     |   --master 等待超時的次數
| Rpl_semi_sync_master_status                | ON    |      --標記master如今是不是半同步複製狀態
| Rpl_semi_sync_master_timefunc_failures     | 0     |     --master調用時間(如gettimeofday())失敗的次數    
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |    --master花在每一個事務上的平均等待時間
| Rpl_semi_sync_master_tx_wait_time          | 0     |    --master花在事物上總的等待時間
| Rpl_semi_sync_master_tx_waits              | 0     |    --master事物等待次數
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |    --後來的先到了,而先來的尚未到的次數
| Rpl_semi_sync_master_wait_sessions         | 0     |    --當前有多少個session由於slave回覆而形成等待
| Rpl_semi_sync_master_yes_tx                | 0     |    --標記slave是否在半同步狀態
+--------------------------------------------+-------+




6,在slave上查看狀態就只有下面一條信息
slave > show global status like 'rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+


第三大步
測試:

master > insert into a values (3);
Query OK, 1 row affected (0.01 sec)

master > show global status like 'rpl_semi_sync%_yes_tx'; 
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_yes_tx |  1    |   --表示此次事物成功從slave返回一次確認信號
+-----------------------------+-------+


模擬錯誤,把slave上的mysql停掉


--再回到master上測試
master> insert into a values (4);
Query OK, 1 row affected (10.00 sec)    --此次插入一個值須要等待10秒(默認的等待時間)

master> insert into a values (5);
Query OK, 1 row affected (0.01 sec)    --如今自動轉成了原來的異步模式(相似oracle DG裏的最大性能模式)


再次把slave啓動,看到半同步複製沒啓來,是異步模式
從新按下面的步驟把同步模式再啓起來就能夠了

slave> set global rpl_semi_sync_slave_enabled=on;
slave> stop slave IO_THREAD;
slave> start slave IO_THREAD;

slave啓起來後,查看錶,發現剛纔slave關閉期間的那幾條數據仍是會自動複製過來,數據又回到一致


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



mysql的延時複製(IO線程是實時,只是把SQL線程延時了)


           異步或同步複製    
        A  ---------->   B
             |
            |-------> C
              延時1天

誤刪除一張用了好幾年的數據表
恢復方法:
1,經過每週的備份來恢復(假設週一0點全備,週三誤刪除)
先恢復週一的全備到測試庫上,而後再恢復全備到如今的二進制日誌(除了誤刪除的那句),再把那張表導出來,導回到生產庫上
2,徹底經過二進制日誌來恢復
須要把這幾年內全部的二進制日誌先合併,再經過sed,grep,awk等把這張表從建表到如今的全部操做按順序找出來(固然要除掉你最後誤刪除的那條),而後應用回去
3,有延時複製的話,在C上導出這張表,導回A



mysql開源管理工具 


軟件路徑在
筆記目錄下/mysql/mysql_soft/maatkit-7540.tar.gz


--在mysql AB的slave上安裝(只須要在slave上安裝,包含下面的步驟都是在slave上作的)
# tar xf maatkit-7540.tar.gz -C /usr/src/
# cd /usr/src/maatkit-7540/

安裝方法README文件裏有寫
# perl Makefile.PL     --若是不成功,須要安裝perl有關的多個包,能夠yum install perl* 
# make install


# ls bin/        --這些命令,就是各個管理工具
mk-archiver               mk-purge-logs
mk-checksum-filter        mk-query-advisor
mk-config-diff            mk-query-digest
mk-deadlock-logger        mk-query-profiler
mk-duplicate-key-checker  mk-show-grants
mk-error-log              mk-slave-delay
mk-fifo-split             mk-slave-find
mk-find                   mk-slave-move
mk-heartbeat              mk-slave-prefetch
mk-index-usage            mk-slave-restart
mk-kill                   mk-table-checksum
mk-loadavg                mk-table-sync
mk-log-player             mk-table-usage
mk-merge-mqd-results      mk-tcp-model
mk-parallel-dump          mk-upgrade
mk-parallel-restore       mk-variable-advisor
mk-profile-compact        mk-visual-explain


--使用--help查看一個命令的使用方法
# mk-slave-delay --help
mk-slave-delay starts and stops a slave server as needed to make it lag behind
the master.  The SLAVE-HOST and MASTER-HOST use DSN syntax, and values are
copied from the SLAVE-HOST to the MASTER-HOST if omitted.  For more details,
please use the --help option, or try 'perldoc /usr/bin/mk-slave-delay' for
complete documentation.



--mysql AB(不管同步或異步)正在運行OK的狀況下,使用下面的命令在slave上運行;作之間建議把時間同步一下

# mk-slave-delay --defaults-file=/etc/my.cnf --delay=1m --interval=15s --user=root --password=123  --quiet localhost &

--表示延時1分鐘,纔會應用SQL線程;這裏是測試因此才使用很小的時間,實際狀況能夠調成1小時或2小時

測試:

在master上隨便插入幾條數據

而後在slave上發現沒有立刻同步過來
slave > show slave status\G;   --查看狀態會發現SQL線程狀態爲NO

        Slave_IO_Running: Yes
        Slave_SQL_Running: NO


大概等1分鐘,就會自動延時同步過來了;
--注意:日誌已經傳到slave的relay-bin log裏了,但由SQL線程延時去解析
相關文章
相關標籤/搜索