from:http://blog.csdn.net/signmem/article/details/17379427

特色
MySQL/Galera 是一种多主同步集群,但只限于使用 MySQL/InnoDB 引擎,并具有下面特点
同步复制
多个主服务器的拓扑结构
可以在任意节点上进行读写
自动控制成员,自动删除故障节点
自动加入节点
真正给予行级别的并发复制
调度客户连接

优势
参考下面基于 DBMS 集群的解决方法
不存在从服务器角色
不存在事务丢失
读写操作可根据需要进行随意扩展
更少的闩操作


知识点
MySQL/Galera 集群使用 Galera 库执行复制,对应 Galera 复制接口,我们需要MySQL 服务器支持 wsrep API 接口
http://www.codership.com/products/mysql-write-set-replication-project


是否可以使用 MySQL 而不使用 mariadb?
不可以,因为 mysql 中没有支持 wsrep_ 数据复制的参数,当然代码级别上也具有很大差别

 

工作原理


mariadb 可以看做是常见的数据库,负责连接应用(web, API 等)
单纯的 mariadb  无法实现多个主服务器数据同步
多台数据库中数据同步由 wsrep 接口实现

最终目标,实现多个 MySQL 同时读写 

wsrep API
wsrep API 是一种数据库插件接口,比较类似一种应用程序,主要针对写复制
该程序主要用于定义应用程序如何调用复制库实现回写
wsrep API 由支持改库的应用程序动态装载


全局事务ID(GTID)
wsrep API 描述下面复制模型,一个应用程序,如数据库当前的一个对象,当前被客户端修改,对象改变导致事务产生一系列的原子性改变, 在集群中所有的节点都具备相同的对象,并由同步复制应用都各自节点,按照相同的顺序产生相同变化从而实现数据同步


到最后,wsrep API 将会分配一个全局事务ID 该 ID 具有下面功能
标识对象的改变
标识对象自身 ID 最后状态(正常情况下,ID 是连续不中断的)

GTID 包含
一个 UUID 作为对象标识及经历改变的序号,序号会发生连续的改变
GTID 允许比较应用程序状态,建立对象改变的顺序,决定对象的变化是否需要更新 GTID
通常 GTID 会卑记录成下面格式
45eec521-2f34-11e0-0800-2a36050b826b:94530586304

 

言归正传,我们需要编译 mariadb-mysql  及  galera 插件

galera/mysql 编译步骤

https://downloads.mariadb.org/interstitial/mariadb-galera-5.5.33a/kvm-tarbake-jaunty-x86/mariadb-galera-5.5.33a.tar.gz/from/http://mirrors.scie.in/mariadb

yum install -y cmake

tar xf mariadb-galera-5.5.33a.tar.gz
cd mariadb-5.5.33a/
cmake -LAH

参考 CMakeCache.txt 文件中的配置信息

  1. cmake -DINSTALL_MYSQLDATADIR:STRING=/mdb -DINSTALL_UNIX_ADDRDIR:STRING=/var/run/mysqld/mysql5.socket  
  2. make  
  3. make install  


默认情况下, mariadb  安装在  /usr/local/mysql

 

galera 编译

https://launchpad.net/galera/2.x/23.2.7/+download/galera-23.2.7-src.tar.gz

添加数据源

  1. baseurl=http://mirror.neu.edu.cn/fedora/epel//6Server/x86_64/  

添加下面软件包

  1. yum erase -y mysql.x86_64 mysql-devel.x86_64 mysql-libs.x86_64    
  2. yum install -y boost-devel.x86_64 libodb-boost-devel.x86_64  bzr scons  


解压 galera-23.2.7-src.tar.gz 并进行编译

  1. cd /usr/src  
  2. tar xf galera-23.2.7-src.tar.gz  
  3. cd galera-23.2.7-src  
  4. scons  


注: scons 为编译命令
 

编译后能生成 libgalera_smm.so

复制编译好的库至下面位置 /usr/local/galera/lib/libgalera_smm.so

  1. mkdir /usr/local/galera/lib -p  
  2. cp /usr/src/galera-23.2.7-src/libgalera_smm.so /usr/local/galera/lib/libgalera_smm.so  


复制 启动脚本 /usr/src/galera-23.2.7-src/scripts/mysql/mysql-galera 到 /usr/local

  1. cp  /usr/src/galera-23.2.7-src/scripts/mysql/mysql-galera /usr/local  


创建 /usr/local/mysql/etc/my.cnf

  1. [mysqld]  
  2. basedir=/usr/local/mysql  
  3. big-tables  
  4. bind-address=0.0.0.0  
  5. character-set-server=utf8  
  6. datadir=/mdb  
  7. log-error=/var/log/mysqld/mysql5-error.log  
  8. socket=/var/run/mysqld/mysql5.socket  
  9. pid-file=/var/run/mysqld/mysql5.pid  
  10. port=3306  
  11. user=mysql  
  12.   
  13. binlog_format = ROW  
  14. binlog_cache_size = 1M  
  15. character_set_server = utf8  
  16. collation_server = utf8_general_ci  
  17.   
  18. default-storage-engine = InnoDB  
  19.   
  20. expire_logs_days = 10  
  21.   
  22. innodb_buffer_pool_size = 300M  
  23. innodb_thread_concurrency = 16  
  24. innodb_log_buffer_size = 8M  
  25.   
  26. innodb_doublewrite = 1  
  27. innodb_file_per_table = 1  
  28. innodb_flush_log_at_trx_commit = 2  
  29.   
  30. server-id = 1  
  31. max_connections = 1000  
  32.   
  33. net_buffer_length = 8K  
  34. open-files-limit = 65535  
  35.   
  36. wsrep_cluster_address = 'gcomm://192.168.200.163,192.168.200.171,172.18.8.49,172.18.8.50'  
  37. wsrep_provider = /usr/local/galera/lib/libgalera_smm.so  
  38. wsrep_retry_autocommit = 0  
  39. wsrep_sst_method = rsync  
  40. wsrep_provider_options="gcache.size=256m; gcache.page_size=256m"  
  41. wsrep_slave_threads=16  
  42.   
  43. wsrep_cluster_name='my_cluster'  
  44. wsrep_node_name='db5'  
  45.   
  46. wsrep_sst_auth=tt:tt123  

 


maridb 启动测试

初始化数据库

  1. mkdir /mdb  
  2. cd /usr/local/mysql  
  3. ./scripts/install_mysql_db --datadir=/mdb  


启动脚本 /etc/rc.d/init.d/mysql5 确保文件可执行权限

  1. #!/bin/sh  
  2. # chkconfig: 2345 64 36  
  3. # description: A very fast and reliable SQL database engine.  
  4. <p>basedir=/usr/local/mysql  
  5. datadir=/mdb</p><p># Default value, in seconds, afterwhich the script should timeout waiting  
  6. # for server start.  
  7. # Value here is overriden by value in my.cnf.  
  8. # 0 means don't wait at all  
  9. # Negative numbers mean to wait indefinitely  
  10. service_startup_timeout=900  
  11. startup_sleep=1</p><p># Lock directory for RedHat / SuSE.  
  12. lockdir='/var/lock/subsys'  
  13. lock_file_path="$lockdir/mysql"</p><p># The following variables are only set for letting mysql.server find things.</p><p># Set some defaults  
  14. mysqld_pid_file_path=/var/run/mysqld/mysql5.pid  
  15. if test -z "$basedir"  
  16. then  
  17.   basedir=/usr/local/mysql  
  18.   bindir=/usr/local/mysql/bin  
  19.   if test -z "$datadir"  
  20.   then  
  21.     datadir=/usr/local/mysql/data  
  22.   fi  
  23.   sbindir=/usr/local/mysql/bin  
  24.   libexecdir=/usr/local/mysql/bin  
  25. </p><p>else  
  26.   bindir="$basedir/bin"  
  27.   if test -z "$datadir"  
  28.   then  
  29.     datadir="$basedir/data"  
  30.   fi  
  31.   sbindir="$basedir/sbin"  
  32.   if test -f "$basedir/bin/mysqld"  
  33.   then  
  34.     libexecdir="$basedir/bin"  
  35.   else  
  36.     libexecdir="$basedir/libexec"  
  37.   fi  
  38. fi</p><p># datadir_set is used to determine if datadir was set (and so should be  
  39. # *not* set inside of the --basedir= handler.)  
  40. datadir_set=</p><p>#  
  41. # Use LSB init script functions for printing messages, if possible  
  42. #  
  43. lsb_functions="/lib/lsb/init-functions"  
  44. if test -f $lsb_functions ; then  
  45.   . $lsb_functions  
  46. else  
  47.   log_success_msg()  
  48.   {  
  49.     echo " SUCCESS! $@"  
  50.   }  
  51.   log_failure_msg()  
  52.   {  
  53.     echo " ERROR! $@"  
  54.   }  
  55. fi</p><p>PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"  
  56. </p><p>export PATH</p><p>mode=$1    # start or stop</p><p>[ $# -ge 1 ] && shift</p><p>  
  57. other_args="$*"   # uncommon, but needed when called from an RPM upgrade action  
  58.            # Expected: "--skip-networking --skip-grant-tables"  
  59.            # They are not checked here, intentionally, as it is the resposibility  
  60.            # of the "spec" file author to give correct arguments only.</p><p>case `echo "testing\c"`,`echo -n testing` in  
  61.     *c*,-n*) echo_n=   echo_c=     ;;  
  62.     *c*,*)   echo_n=-n echo_c=     ;;  
  63.     *)       echo_n=   echo_c='\c' ;;  
  64. esac</p><p>parse_server_arguments() {  
  65.   for arg do  
  66.     case "$arg" in  
  67.       --basedir=*)  basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`  
  68.                     bindir="$basedir/bin"  
  69.                     if test -z "$datadir_set"; then  
  70.                       datadir="$basedir/data"  
  71.                     fi  
  72.                     sbindir="$basedir/sbin"  
  73.                     if test -f "$basedir/bin/mysqld"  
  74.                     then  
  75.                       libexecdir="$basedir/bin"  
  76.                     else  
  77.                       libexecdir="$basedir/libexec"  
  78.                     fi  
  79.                     libexecdir="$basedir/libexec"  
  80.         ;;  
  81.       --datadir=*)  datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`  
  82.                     datadir_set=1  
  83. </p><p>        ;;  
  84.       --pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;  
  85.       --service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;  
  86.     esac  
  87.   done  
  88. }</p><p>wait_for_pid () {  
  89.   verb="$1"           # created | removed  
  90.   pid="$2"            # process ID of the program operating on the pid-file  
  91.   pid_file_path="$3" # path to the PID file.</p><p>  sst_progress_file=$datadir/sst_in_progress  
  92.   i=0  
  93.   avoid_race_condition="by checking again"</p><p>  while test $i -ne $service_startup_timeout ; do</p><p>    case "$verb" in  
  94.       'created')  
  95.         # wait for a PID-file to pop into existence.  
  96.         test -s "$pid_file_path" && i='' && break  
  97.         ;;  
  98.       'removed')  
  99.         # wait for this PID-file to disappear  
  100.         test ! -s "$pid_file_path" && i='' && break  
  101.         ;;  
  102.       *)  
  103.         echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"  
  104.         exit 1  
  105.         ;;  
  106.     esac</p><p>    # if server isn't running, then pid-file will never be updated  
  107.     if test -n "$pid"; then  
  108.       if kill -0 "$pid" 2>/dev/null; then  
  109.         :  # the server still runs  
  110. </p><p>      else  
  111.         # The server may have exited between the last pid-file check and now.  
  112.         if test -n "$avoid_race_condition"; then  
  113.           avoid_race_condition=""  
  114.           continue  # Check again.  
  115.         fi</p><p>        # there's nothing that will affect the file.  
  116.         log_failure_msg "The server quit without updating PID file ($pid_file_path)."  
  117.         return 1  # not waiting any more.  
  118.       fi  
  119.     fi</p><p>    if test -e $sst_progress_file && [ $startup_sleep -ne 100 ];then  
  120.         echo $echo_n "SST in progress, setting sleep higher"  
  121.         startup_sleep=100  
  122.     fi</p><p>    echo $echo_n ".$echo_c"  
  123.     i=`expr $i + 1`  
  124.     sleep $startup_sleep</p><p>  done</p><p>  if test -z "$i" ; then  
  125.     log_success_msg  
  126.     return 0  
  127.   else  
  128.     log_failure_msg  
  129.     return 1  
  130.   fi  
  131. }</p><p># Get arguments from the my.cnf file,  
  132. # the only group, which is read from now on is [mysqld]  
  133. if test -x ./bin/my_print_defaults  
  134. then  
  135. </p><p>  print_defaults="./bin/my_print_defaults"  
  136. elif test -x $bindir/my_print_defaults  
  137. then  
  138.   print_defaults="$bindir/my_print_defaults"  
  139. elif test -x $bindir/mysql_print_defaults  
  140. then  
  141.   print_defaults="$bindir/mysql_print_defaults"  
  142. else  
  143.   # Try to find basedir in /etc/my.cnf  
  144.   conf=/usr/local/mysql/etc/my.cnf  
  145.   print_defaults=  
  146.   if test -r $conf  
  147.   then  
  148.     subpat='^[^=]*basedir[^=]*=\(.*\)$'  
  149.     dirs=`sed -e "/$subpat/!d" -e 's//\1/' $conf`  
  150.     for d in $dirs  
  151.     do  
  152.       d=`echo $d | sed -e 's/[  ]//g'`  
  153.       if test -x "$d/bin/my_print_defaults"  
  154.       then  
  155.         print_defaults="$d/bin/my_print_defaults"  
  156.         break  
  157.       fi  
  158.       if test -x "$d/bin/mysql_print_defaults"  
  159.       then  
  160.         print_defaults="$d/bin/mysql_print_defaults"  
  161.         break  
  162.       fi  
  163.     done  
  164.   fi</p><p>  # Hope it's in the PATH ... but I doubt it  
  165.   test -z "$print_defaults" && print_defaults="my_print_defaults"  
  166. fi</p><p>#  
  167. # Read defaults file from 'basedir'.   If there is no defaults file there  
  168. </p><p># check if it's in the old (depricated) place (datadir) and read it from there  
  169. #</p><p>extra_args=""  
  170. if test -r "$basedir/my.cnf"  
  171. then  
  172.   extra_args="-e $basedir/my.cnf"  
  173. else  
  174.   if test -r "$datadir/my.cnf"  
  175.   then  
  176.     extra_args="-e $datadir/my.cnf"  
  177.   fi  
  178. fi</p><p>parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`</p><p>#  
  179. # Set pid file if not given  
  180. #  
  181. if test -z "$mysqld_pid_file_path"  
  182. then  
  183.   mysqld_pid_file_path=$datadir/`hostname`.pid  
  184. else  
  185.   case "$mysqld_pid_file_path" in  
  186.     /* ) ;;  
  187.     * )  mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;  
  188.   esac  
  189. fi</p><p>case "$mode" in  
  190.   'start')  
  191.     # Start daemon</p><p>    # Safeguard (relative paths, core dumps..)  
  192.     cd $basedir</p><p>    echo $echo_n "Starting MySQL"  
  193. </p><p>    if test -x $bindir/mysqld_safe  
  194.     then  
  195.       # Give extra arguments to mysqld with the my.cnf file. This script  
  196.       # may be overwritten at next upgrade.  
  197.       $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null 2>&1 &  
  198.       wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?</p><p>      # Make lock for RedHat / SuSE  
  199.       if test -w "$lockdir"  
  200.       then  
  201.         touch "$lock_file_path"  
  202.       fi</p><p>      exit $return_value  
  203.     else  
  204.       log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"  
  205.     fi  
  206.     ;;</p><p>  'stop')  
  207.     # Stop daemon. We use a signal here to avoid having to know the  
  208.     # root password.</p><p>    if test -s "$mysqld_pid_file_path"  
  209.     then  
  210.       mysqld_pid=`cat "$mysqld_pid_file_path"`</p><p>      if (kill -0 $mysqld_pid 2>/dev/null)  
  211.       then  
  212.         echo $echo_n "Shutting down MySQL"  
  213.         kill $mysqld_pid  
  214.         # mysqld should remove the pid file when it exits, so wait for it.  
  215.         wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?  
  216.       else  
  217.         log_failure_msg "MySQL server process #$mysqld_pid is not running!"  
  218.         rm "$mysqld_pid_file_path"  
  219.       fi  
  220. </p><p>      # Delete lock for RedHat / SuSE  
  221.       if test -f "$lock_file_path"  
  222.       then  
  223.         rm -f "$lock_file_path"  
  224.       fi  
  225.       exit $return_value  
  226.     else  
  227.       log_failure_msg "MySQL server PID file could not be found!"  
  228.     fi  
  229.     ;;</p><p>  'restart')  
  230.     # Stop the service and regardless of whether it was  
  231.     # running or not, start it again.  
  232.     if $0 stop  $other_args; then  
  233.       $0 start $other_args  
  234.     else  
  235.       log_failure_msg "Failed to stop running server, so refusing to try to start."  
  236.       exit 1  
  237.     fi  
  238.     ;;</p><p>  'reload'|'force-reload')  
  239.     if test -s "$mysqld_pid_file_path" ; then  
  240.       read mysqld_pid <  "$mysqld_pid_file_path"  
  241.       kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"  
  242.       touch "$mysqld_pid_file_path"  
  243.     else  
  244.       log_failure_msg "MySQL PID file could not be found!"  
  245.       exit 1  
  246.     fi  
  247.     ;;  
  248.   'status')  
  249.     # First, check to see if pid file exists  
  250.     if test -s "$mysqld_pid_file_path" ; then  
  251.       read mysqld_pid < "$mysqld_pid_file_path"  
  252. </p><p>      if kill -0 $mysqld_pid 2>/dev/null ; then  
  253.         log_success_msg "MySQL running ($mysqld_pid)"  
  254.         exit 0  
  255.       else  
  256.         log_failure_msg "MySQL is not running, but PID file exists"  
  257.         exit 1  
  258.       fi  
  259.     else  
  260.       # Try to find appropriate mysqld process  
  261.       mysqld_pid=`pidof $libexecdir/mysqld`</p><p>      # test if multiple pids exist  
  262.       pid_count=`echo $mysqld_pid | wc -w`  
  263.       if test $pid_count -gt 1 ; then  
  264.         log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)"  
  265.         exit 5  
  266.       elif test -z $mysqld_pid ; then  
  267.         if test -f "$lock_file_path" ; then  
  268.           log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"  
  269.           exit 2  
  270.         fi  
  271.         log_failure_msg "MySQL is not running"  
  272.         exit 3  
  273.       else  
  274.         log_failure_msg "MySQL is running but PID file could not be found"  
  275.         exit 4  
  276.       fi  
  277.     fi  
  278.     ;;  
  279.   'configtest')  
  280.     # Safeguard (relative paths, core dumps..)  
  281.     cd $basedir  
  282.     echo $echo_n "Testing MySQL configuration syntax"  
  283.     daemon=$bindir/mysqld  
  284.     if test -x $libexecdir/mysqld  
  285.     then  
  286.       daemon=$libexecdir/mysqld  
  287.     elif test -x $sbindir/mysqld  
  288.     then  
  289.       daemon=$sbindir/mysqld  
  290.     elif test -x `which mysqld`  
  291.     then  
  292.       daemon=`which mysqld`  
  293.     else  
  294.       log_failure_msg "Unable to locate the mysqld binary!"  
  295.       exit 1  
  296.     fi  
  297.     help_out=`$daemon --help 2>&1`; r=$?  
  298.     if test "$r" != 0 ; then  
  299.       log_failure_msg "$help_out"  
  300.       log_failure_msg "There are syntax errors in the server configuration. Please fix them!"  
  301.     else  
  302.       log_success_msg "Syntax OK"  
  303.     fi  
  304.     exit $r  
  305.     ;;  
  306.   'bootstrap')  
  307.       # Bootstrap the cluster, start the first node  
  308.       # that initiate the cluster  
  309.       echo $echo_n "Bootstrapping the cluster"  
  310.       $0 start $other_args --wsrep-new-cluster  
  311.       ;;  
  312.   *)  
  313.       # usage  
  314.       basename=`basename "$0"`  
  315.       echo "Usage: $basename  {start|stop|restart|reload|force-reload|status|configtest|bootstrap}  [ MySQL server options ]"  
  316.       exit 1  
  317.     ;;  
  318. esac</p><p>exit 0  
  319. </p>  

 

启动每一台数据库

  1. service mysql5 start  


在每台数据库中建立下面用户, 用于 sst 认证 (以 root 登入 mysql 数据库后执行下面的 SQL 语句

  1. GRANT USAGE ON *.* to tt@'%' IDENTIFIED BY 'tt123';  
  2. GRANT ALL PRIVILEGES on *.* to tt@'%';  
  3. GRANT USAGE ON *.* to tt@'localhost' IDENTIFIED BY 'tt123';  
  4. GRANT ALL PRIVILEGES on *.* to tt@'localhost';  
  5. flush privileges;  


关闭所有数据库, 集群启动前, 不需要启动任何一台的数据库

  1. service mysql5 stop  

 
创建并加入集群

集群中第一个节点启动 (192.168.200.163)
创建软链接,并启动集群,集群启动过程中会自动启动 mariadb

  1. ln -s /usr/local/mysql/bin/ /usr/local/mysql/sbin  
  2. cd /usr/local/  
  3. ./mysql-galera -g  gcomm://  start  

 

测试是否成功启动方法, 查询是否会自动启动 4567 端口

  1. [root@db2 local]# netstat -ntl  
  2. Active Internet connections (only servers)  
  3. Proto Recv-Q Send-Q Local Address               Foreign Address             State  
  4. tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN  
  5. tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN  
  6. tcp        0      0 0.0.0.0:4567                0.0.0.0:*                   LISTEN  

 

登录 mysql 之后,查询当前是否启用 galera 插件

  1. MariaDB [(none)]> show status like 'wsrep_ready';  
  2. +---------------+-------+  
  3. | Variable_name | Value |  
  4. +---------------+-------+  
  5. | wsrep_ready   | ON    |  
  6. +---------------+-------+  
  7. 1 row in set (0.00 sec)  


注,on 为已经启动插件状态


关闭方法

  1. cd /usr/local  
  2. ./mysql-galera stop  


其他节点加入集群方法

第一台 (192.168.200.163) 节点已经启动成功
第二台 (192.168.200.171) 需要加入集群

  1. cd /usr/local/  
  2. ./mysql-galera -g  gcomm://192.168.200.163 start  


可按上述方法进行集群启动测试, 也可以参照下面方法, 观察集群地址是否增加两个服务器地址

  1. MariaDB [(none)]> show status like 'wsrep_incoming_addresses';  
  2. +--------------------------+-------------------------------------------+  
  3. | Variable_name            | Value                                     |  
  4. +--------------------------+-------------------------------------------+  
  5. | wsrep_incoming_addresses | 192.168.200.171:3306,192.168.200.163:3306 |  
  6. +--------------------------+-------------------------------------------+  
  7. 1 row in set (0.00 sec)  



第三台 (172.18.8.49) 需要加入集群

  1. cd /usr/local/  
  2. ./mysql-galera -g  gcomm://192.168.200.163,192.168.200.171 start  


第四台 (172.18.8.50) 需要加入集群

  1. cd /usr/local/  
  2. ./mysql-galera -g  gcomm://192.168.200.163,192.168.200.171,172.18.8.49 start  


 

  1. 注: 每次集群启动, 将会启用数据同步机制,令每个集群中的数据同步  
  2.   
  3. 假如,集群工作期间,节点 3(172.18.8.49) 脱离集群,重启,发生故障  
  4. 而脱机期间,节点1,2,4 仍可继续工作  
  5. 当节点3 重新在线时,加入集群前,将会自动进行数据同步  
  6.   
  7. 重新在线方法与上文中加入节点方法一致  
  8.   
  9. 另外,假如觉得要定义所有的服务器地址麻烦,可以加入集群时候只定义其中一台的地址,如 gcomm://192.168.200.163 集群也能够自动在加入后添加其他集群 url地址  


常见 wsrep 参数注释

  1. MariaDB [terry]> show status like 'wsrep%';  
  2. +----------------------------+--------------------------------------+  
  3. | Variable_name              | Value                                |  
  4. +----------------------------+--------------------------------------+  
  5. | wsrep_local_state_uuid     | bb5b9e17-66c8-11e3-86ba-96854521d205 | uuid 集群唯一标记  
  6. | wsrep_protocol_version     | 4                                    |  
  7. | wsrep_last_committed       | 16                                   | sql 提交记录  
  8. | wsrep_replicated           | 4                                    | 随着复制发出的次数  
  9. | wsrep_replicated_bytes     | 692                                  | 数据复制发出的字节数  
  10. | wsrep_received             | 18                                   | 数据复制接收次数  
  11. | wsrep_received_bytes       | 3070                                 | 数据复制接收的字节数  
  12. | wsrep_local_commits        | 4                                    | 本地执行的 sql  
  13. | wsrep_local_cert_failures  | 0                                    | 本地失败事务  
  14. | wsrep_local_bf_aborts      | 0                                    |从执行事务过程被本地中断  
  15. | wsrep_local_replays        | 0                                    |  
  16. | wsrep_local_send_queue     | 0                                    | 本地发出的队列  
  17. | wsrep_local_send_queue_avg | 0.142857                             | 队列平均时间间隔  
  18. | wsrep_local_recv_queue     | 0                                    | 本地接收队列  
  19. | wsrep_local_recv_queue_avg | 0.000000                             | 本地接收时间间隔  
  20. | wsrep_flow_control_paused  | 0.000000                             |  
  21. | wsrep_flow_control_sent    | 0                                    |  
  22. | wsrep_flow_control_recv    | 0                                    |  
  23. | wsrep_cert_deps_distance   | 0.000000                             | 并发数量   
  24. | wsrep_apply_oooe           | 0.000000                             |  
  25. | wsrep_apply_oool           | 0.000000                             |  
  26. | wsrep_apply_window         | 1.000000                             |  
  27. | wsrep_commit_oooe          | 0.000000                             |  
  28. | wsrep_commit_oool          | 0.000000                             |  
  29. | wsrep_commit_window        | 1.000000                             |  
  30. | wsrep_local_state          | 4                                    |  
  31. | wsrep_local_state_comment  | Synced                               |  
  32. | wsrep_cert_index_size      | 0                                    |  
  33. | wsrep_causal_reads         | 0                                    |  
  34. | wsrep_incoming_addresses   | 172.18.8.50:3306,172.18.8.49:3306    | 连接中的数据库  
  35. | wsrep_cluster_conf_id      | 18                                   |  
  36. | wsrep_cluster_size         | 2                                    | 集群成员个数  
  37. | wsrep_cluster_state_uuid   | bb5b9e17-66c8-11e3-86ba-96854521d205 | 集群 ID  
  38. | wsrep_cluster_status       | Primary                              | 主服务器  
  39. | wsrep_connected            | ON                                   | 当前是否连接中  
  40. | wsrep_local_index          | 1                                    |  
  41. | wsrep_provider_name        | Galera                               |  
  42. | wsrep_provider_vendor      | Codership Oy <info@codership.com>    |  
  43. | wsrep_provider_version     | 2.7(rXXXX)                           |  
  44. | wsrep_ready                | ON                                   | 插件是否应用中  
  45. +----------------------------+--------------------------------------+  
  46. 40 rows in set (0.05 sec)  


时间关系,还没有时间进行压力测试,也没有比对  galera 与  Percona XtraDB Cluster 集群之间区别

另,如使用 rpm 则十分方便,网路很多教程, 不详细描述

 auto_increment

当更多的 MariaDB 加入到集群之后,集群中的数据库会自动进行协调,并且自动定义偏移量, 这个比较人性化,自动化,如下描述

db1:

  1. MariaDB [(none)]> show variables like 'auto_increment%';  
  2. +--------------------------+-------+  
  3. | Variable_name            | Value |  
  4. +--------------------------+-------+  
  5. | auto_increment_increment | 4     |  
  6. | auto_increment_offset    | 3     |  
  7. +--------------------------+-------+  
  8. 2 rows in set (0.00 sec)  


db2:

  1. MariaDB [(none)]> show variables like 'auto_increment%';  
  2. +--------------------------+-------+  
  3. | Variable_name            | Value |  
  4. +--------------------------+-------+  
  5. | auto_increment_increment | 4     |  
  6. | auto_increment_offset    | 4     |  
  7. +------------------------  


db3:

  1. MariaDB [(none)]> show variables like 'auto_increment%';  
  2. +--------------------------+-------+  
  3. | Variable_name            | Value |  
  4. +--------------------------+-------+  
  5. | auto_increment_increment | 4     |  
  6. | auto_increment_offset    | 2     |  
  7. +--------------------------+-------+  
  8. 2 rows in set (0.00 sec)  


db4:

  1. MariaDB [(none)]> show variables like 'auto_increment%';  
  2. +--------------------------+-------+  
  3. | Variable_name            | Value |  
  4. +--------------------------+-------+  
  5. | auto_increment_increment | 4     |  
  6. | auto_increment_offset    | 1     |  
  7. +--------------------------+-------+  
  8. 2 rows in set (0.00 sec)  


当前加入集群中共 4 个节点, 如上所见,每个集群中都会每次在数字递增时候递增 4 位, 而数字起始值为加入集群的顺序 

 
模拟测试1

创建测试表

  1. MariaDB [(none)]> desc terry.t2;  
  2. +-------+-------------+------+-----+-------------------+-----------------------------+  
  3. | Field | Type        | Null | Key | Default           | Extra                       |  
  4. +-------+-------------+------+-----+-------------------+-----------------------------+  
  5. | id    | int(11)     | NO   | PRI | NULL              | auto_increment              |  
  6. | name  | varchar(20) | YES  |     | NULL              |                             |  
  7. | time  | timestamp   | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |  
  8. +-------+-------------+------+-----+-------------------+-----------------------------+  
  9. 3 rows in set (0.00 sec)  

 

在每台电脑中创建对应的数据插入脚本  (太大量的并发插入会导致服务器不断脱离集群,最终只剩下一次,因此减少数据插入量)

  1. [root@db6 mdb]# cat /tmp/in.sh  
  2. #!/bin/bash  
  3. for (( a=1 ; a<=1000 ; a++ ))  
  4. do  
  5.         name="db6.$a"  
  6.         mysql -u terry -p123 -e "insert into terry.t2 (name, time) values (\"$name\", now())"  
  7. done  


目的:同时在 4 台电脑中进行数据插入,每台插入 1000 行(并发执行)

插入过程中, 会出现锁,有一个数据库集群会自动脱离集群  >_<"

  1. MySQL thread id 16, OS thread handle 0x7f2f2019a700, query id 4666 applied write set 183192  
  2. TABLE LOCK table `terry`.`t2` trx id 2D3EF lock mode IX  
  3. ---TRANSACTION 2D3EE, ACTIVE 0 sec  
  4. mysql tables in use 1, locked 1  
  5. 1 lock struct(s), heap size 376, 0 row lock(s), undo log entries 1  
  6. MySQL thread id 633, OS thread handle 0x7f2f20076700, query id 4664 localhost terry query end  
  7. insert into terry.t2 (name, time) values ("db5.603", now())  
  8. TABLE LOCK table `terry`.`t2` trx id 2D3EE lock mode IX  
  9. ---TRANSACTION 2D3ED, ACTIVE (PREPARED) 0 sec preparing  
  10. 1 lock struct(s), heap size 376, 0 row lock(s), undo log entries 1  
  11. MySQL thread id 3, OS thread handle 0x7f2f3be4e700, query id 4662 committing 183190  

 

参考其他三台 时间返回值
db1 (使用 13 秒)
db2 (使用 24秒)
db3(使用14秒)
db4(写入 35 条数据后 crash)