python自动创建mysql的从库脚本

     本脚本主要用于创建mysql主从的从库,并且主库已经配置好相关的主从参数,主库上面有需要同步的数据库备份,在从库上执行此脚本,通过内网取得主库的配置文件、数据库备份、主库的权限库等用于从库的创建,自动获得需要同步主库的bin-log位置及pos点(本脚本的备份是晚上0点备份,此脚本已经在我公司多个游戏数据库上应用,还不错,大家可以看看!

 

  
  
  
  
  1. #!/usr/bin/env python 
  2. # -*- coding: utf-8 -*- 
  3. ############################################################################## 
  4. # @Author:       wangwei 
  5. # @E-mail:        [email protected] 
  6. # @Create Date:  2012-10-23 
  7. # @Version:      V6 
  8. ############################################################################## 
  9. import paramiko,os,sys,datetime,time,MySQLdb 
  10.  
  11. def log_w(text): 
  12.     logfile = "/home/create_slave.log" 
  13.     now = time.strftime("%Y-%m-%d %H:%M:%S"
  14.     tt = str(now) + "\t" + str(text) + "\n" 
  15.     f = open(logfile,'a+'
  16.     f.write(tt) 
  17.     f.close() 
  18.  
  19. class Database: 
  20.  
  21.     def __init__(self,host): 
  22.         self.user='root' 
  23.         self.password='123456' 
  24.         self.port=22 
  25.         self.today=datetime.date.today().strftime('%Y%m%d'
  26.         self.bindir='/data1/mysql_log' 
  27.         self.host=host 
  28.         if not os.path.isdir(self.bindir): 
  29.             os.makedirs(self.bindir) 
  30.             os.popen("ln -s /data1/mysql_log /mysql_log"
  31.         if not os.path.isdir('/data1/mysql_log/binlog'):  
  32.             os.makedirs('/data1/mysql_log/binlog'
  33.         if not os.path.isdir('/data1/mysql_log/relaylog'): 
  34.             os.makedirs('/data1/mysql_log/relaylog'
  35.         os.popen("chown -R mysql.mysql /data1/mysql_log/"
  36.  
  37.     def check_mysql(self):#检查从库nysql数据库服务是否运行,如在运行则pkill掉,然后跳过权限表启动,为导入数据做准备 
  38.         text = "Check mysql now,Please wait...." 
  39.         log_w(text) 
  40.         print "\033[1;32;40m%s\033[0m" % text 
  41.         os.popen("rm -rf /mysql_log/binlog/* && rm -rf /mysql_log/relaylog/*"
  42.         if not os.path.isdir("/usr/local/mysql"): 
  43.             text = "    Mysql not install,Please install mysql !" 
  44.             log_w(text) 
  45.             print "\033[1;31;40m%s\033[0m" % text 
  46.             sys.exit() 
  47.         if os.popen("netstat -ntlp|grep 3306|wc -l").read().strip() != '0'
  48.             os.popen("pkill mysqld"
  49.         while 1
  50.             if os.popen("netstat -ntlp|grep 3306|wc -l").read().strip() == '0'
  51.                 for f in os.listdir("/home/mysql/data"):#清空此目录中除mysql目录之外的所有文件和目录 
  52.                     if f != 'mysql'
  53.                         os.popen("rm -rf /home/mysql/data/%s" % f) 
  54.                 conm = "/usr/local/mysql/bin/mysqld_safe --defaults-file=/usr/local/mysql/etc/innodb.cnf --datadir=/home/mysql/data --user=mysql --skip-grant-tables &" 
  55.                 os.popen(conm) 
  56.                 break 
  57.             else
  58.                 text = "Mysql not stop,please wait..." 
  59.                 log_w(text) 
  60.                 print text 
  61.                 time.sleep(5
  62.         time.sleep(20
  63.         if os.popen("netstat -ntlp|grep 3306|wc -l").read().strip() == '0'
  64.             text = "Mysql not Running,please start with '--skip-grant-tables' !" 
  65.             log_w(text) 
  66.             print "\033[1;31;40m%s\033[0m" % text 
  67.             sys.exit() 
  68.  
  69.     def export_table(self):#导出当前主库的表结构 
  70.         print "\033[1;32;40m%s\033[0m" % "Export master table and back mysql,Please wait ...." 
  71.         try
  72.             s=paramiko.SSHClient() 
  73.             s.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
  74.             s.connect(self.host,self.port,self.user,self.password) 
  75.             conm = "/usr/local/mysql/bin/mysqldump --add-drop-table -udump -p123456 -d -A|bzip2 -2 > /data/script/db_back/table_%s.bz2 && cp -f /usr/local/mysql/etc/innodb.cnf /data/script/db_back/ && echo $?" % self.today 
  76.             stdin,stdout,stderr=s.exec_command(conm) 
  77.             result = stdout.readlines()[-1].strip() 
  78.             s.close() 
  79.             if result == '0'
  80.                 text = "    Export_table success !" 
  81.                 log_w(text) 
  82.                 print text 
  83.             else
  84.                 text = "Export_table Error !" 
  85.                 log_w(text) 
  86.                 print "\033[1;31;40m%s\033[0m" % text 
  87.                 sys.exit() 
  88.         except Exception,e: 
  89.             text = "SSH connect Error !" 
  90.             log_w(text) 
  91.             print "\033[1;31;40m%s\033[0m" % text 
  92.             sys.exit() 
  93.  
  94.     def down_back(self):#拷贝主库当天的数据库备份和表结构 
  95.         local_dir='/data1/' 
  96.         remote_dir='/data/script/db_back/' 
  97.         try
  98.             t=paramiko.Transport((self.host,self.port)) 
  99.             t.connect(username=self.user,password=self.password) 
  100.             sftp=paramiko.SFTPClient.from_transport(t) 
  101.             files=sftp.listdir(remote_dir) 
  102.             text = "Download back file,Please wait ...." 
  103.             log_w(text) 
  104.             print "\033[1;32;40m%s\033[0m" % text 
  105.             text = '    Beginning to download file  from %s  %s ' % (self.host,datetime.datetime.now()) 
  106.             log_w(text) 
  107.             print text 
  108.             for f in files: 
  109.                 if f.find(self.today) != -1 or f == 'innodb.cnf'
  110.                     text = "        Downloading file:%s:%s" % (self.host,os.path.join(remote_dir,f)) 
  111.                     log_w(text) 
  112.                     print text 
  113.                     sftp.get(os.path.join(remote_dir,f),os.path.join(local_dir,f)) 
  114.                     #sftp.put(os.path.join(local_dir,f),os.path.join(remote_dir,f)) 
  115.             t.close() 
  116.             text = '    Download All back file success %s ' % datetime.datetime.now() 
  117.             log_w(text) 
  118.             print text 
  119.         except Exception,e: 
  120.             text = "SFTP connect Error !" 
  121.             log_w(text) 
  122.             print "\033[1;31;40m%s\033[0m" % text 
  123.             sys.exit() 
  124.  
  125.     def unbz2(self):#解压拷贝的数据库备份和表结构bz2包 
  126.         text = "Decompression file,Please wait ...." 
  127.         log_w(text) 
  128.         print "\033[1;32;40m%s\033[0m" % text 
  129.         text = '    Beginning to Decompression file  from %s' % datetime.datetime.now() 
  130.         log_w(text) 
  131.         print text 
  132.         conm = 'bzip2 -dfk /data1/*%s*.bz2 && echo $?' % self.today 
  133.         bz = os.popen(conm).read().strip() 
  134.         if bz == '0'
  135.             text = '    Decompression file  success %s' % datetime.datetime.now() 
  136.             log_w(text) 
  137.             print text 
  138.         else
  139.             text = "Decompression Error !" 
  140.             log_w(text) 
  141.             print "\033[1;31;40m%s\033[0m" % text 
  142.             sys.exit() 
  143.  
  144.     def restart_mysql(self): 
  145.         text = "Restart mysql Now,Please wait ...." 
  146.         log_w(text) 
  147.         print "\033[1;32;40m%s\033[0m" % text 
  148.         os.popen("rm -rf /usr/local/mysql/etc/innodb.cnf && cp -f /data1/innodb.cnf /usr/local/mysql/etc/innodb.cnf"
  149.         old_id = os.popen("cat /usr/local/mysql/etc/innodb.cnf |grep ^server-id|awk '{print $3}'").read().strip() 
  150.         new_id = int(old_id) + 1 
  151.         os.popen("sed -i 's/server-id       = %s/server-id       = %s/' /usr/local/mysql/etc/innodb.cnf" % (old_id,new_id)) 
  152.         os.popen("/usr/local/mysql/bin/mysqladmin shutdown"
  153.         os.popen("rm -rf /home/mysql/data/*.info && rm -rf /home/mysql/data/ib_logfile*"
  154.         os.popen("/usr/local/mysql/bin/mysqld_safe --defaults-file=/usr/local/mysql/etc/innodb.cnf --datadir=/home/mysql/data --user=mysql &"
  155.         time.sleep(20
  156.         if os.popen("netstat -ntlp|grep 3306|wc -l").read().strip() == '0'
  157.             text = "Mysql restart Error,please check!" 
  158.             log_w(text) 
  159.             print "\033[1;31;40m%s\033[0m" % text 
  160.             sys.exit() 
  161.  
  162.     def import_date(self):#导入表结构和备份数据库 
  163.         text = "Slave import master date,Please wait ...." 
  164.         log_w(text) 
  165.         print "\033[1;32;40m%s\033[0m" % text 
  166.         #导入表结构 
  167.         dir = '/data1/' 
  168.         table = 'table_%s' % self.today 
  169.         conm = "/usr/local/mysql/bin/mysql  < %s%s && echo $?" % (dir,table) 
  170.         result = os.popen(conm).read().strip() 
  171.         if result == '0'
  172.             text = "    Import %s success !" % table 
  173.             log_w(text) 
  174.             print text 
  175.         else
  176.             text = "Import Table structure Error !" 
  177.             log_w(text) 
  178.             print "\033[1;31;40m%s\033[0m" % text 
  179.             sys.exit() 
  180.  
  181.         for f in os.listdir(dir):#导入数据库 
  182.             if os.path.isfile(os.path.join(dir,f)) and (f.find('bz2') == -1and (f.find('table') == -1): 
  183.                 if f.find('wd') != -1 and f.find(self.today) != -1
  184.                     conm = "/usr/local/mysql/bin/mysql < %s && echo $?" % os.path.join(dir,f) 
  185.                     result = os.popen(conm).read().strip() 
  186.                     if result == '0'
  187.                         text = "    Import %s success !" % f 
  188.                         log_w(text) 
  189.                         print text 
  190.                     else
  191.                         text = "Import Database adb Error !" 
  192.                         log_w(text) 
  193.                         print "\033[1;31;40m%s\033[0m" % text 
  194.                         sys.exit() 
  195.  
  196.     def slave_start(self):#启动salve 
  197.         text = "Settings Slave,Please wait ...." 
  198.         log_w(text) 
  199.         print "\033[1;32;40m%s\033[0m" % text 
  200.         binlog,log_pos=self.bin_pos() 
  201.         sql = "change master to master_host='%s',master_user='repl',master_password='123456',master_port=3306,master_log_file='%s',master_log_pos=%s;" % (self.host,binlog,log_pos) 
  202.         try
  203.             conn = MySQLdb.connect(host = '127.0.0.1',user = 'repl_monitor',passwd = '123456',connect_timeout=5
  204.             cursor = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor) 
  205.             #cursor.execute("slave stop;") 
  206.             cursor.execute(sql) 
  207.             cursor.execute("slave start;"
  208.             cursor.execute("show slave status;"
  209.             alldata = cursor.fetchall()[0
  210.             if alldata["Slave_IO_Running"] == "Yes" and alldata["Slave_SQL_Running"] == "Yes"
  211.                 text = "    Settings Slave success!" 
  212.                 log_w(text) 
  213.                 print "\033[1;32;40m%s\033[0m" % text 
  214.                 for key in alldata: 
  215.                     print "%21s :" % key + '\t' + str(alldata[key]) 
  216.                 time.sleep(5
  217.                 print 
  218.                 print "******************************************" 
  219.                 print 
  220.                 cursor.execute("show slave status;"
  221.                 alldata = cursor.fetchall()[0
  222.                 for key in alldata: 
  223.                     print "%21s :" % key + '\t' + str(alldata[key]) 
  224.             else
  225.                 text = "    Settings Slave Error,Please check it!" 
  226.                 log_w(text) 
  227.                 print "\033[1;31;40m%s\033[0m" % text 
  228.             cursor.close() 
  229.             conn.close() 
  230.         except MySQLdb.Error,e: 
  231.             log_w(e) 
  232.             print e 
  233.             sys.exit() 
  234.  
  235.     def bin_pos(self):#获取主库备份前的一个bin-log文件以及它的第一个pos位置 
  236.         dir = '/data1/' 
  237.         for f in os.listdir(dir): 
  238.             if os.path.isfile(os.path.join(dir,f)) and (f.find('bz2') == -1and (f.find('table') == -1): 
  239.                 if f.find('wd') != -1 and f.find(self.today) != -1
  240.                     binlog = f.split('_')[3
  241.                     log_pos = f.split('_')[4
  242.                     return binlog,log_pos 
  243.  
  244. def find_ip():#走中心应用确认本服务器是否用于从库 
  245.     text = "正在从中心应用确认本服务器是否用于从库,稍等......".decode("utf-8").encode("GBK"
  246.     log_w(text) 
  247.     print "\033[1;32;40m%s\033[0m" % text 
  248.     ip = os.popen("cat /etc/sysconfig/network-scripts/ifcfg-eth0|grep IPADDR |awk -F '=' '{print $2}'").read().strip() 
  249.     try
  250.         conn = MySQLdb.connect(host = '192.168.1.110',user = 'root',passwd = '1q2w3e4r',connect_timeout=5
  251.         cursor = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor) 
  252.         sql = "SELECT c.dist_id,c.ip,c.app_name FROM center_app.main_category a, center_app.sub_category b, center_app.app_info c WHERE a.id = b.main_id AND b.dist_id = c.dist_id AND b.main_id = c.main_id AND b.main_id='2' AND c.app_name IN ('ldb','adb','slave') AND c.flag='1' AND c.del_info!=0 AND c.dist_id NOT IN ('0','1','-100','-1','222') AND c.ip='%s'" % ip 
  253.         cursor.execute(sql) 
  254.         alldata = cursor.fetchall()[0
  255.         if alldata["app_name"] == "slave"
  256.             text = "    This server is slave server,server OK !!" 
  257.             log_w(text) 
  258.             print "\033[1;32;40m%s\033[0m" % text 
  259.         else
  260.             text = "    This server is not used slave server,server Error,please check it !!" 
  261.             log_w(text) 
  262.             print "\033[1;31;40m%s\033[0m" % text 
  263.             sys.exit 
  264.         cursor.close() 
  265.         conn.close() 
  266.     except MySQLdb.Error,e: 
  267.         log_w(e) 
  268.         print e 
  269.         sys.exit() 
  270.  
  271. if __name__=="__main__"
  272.     print "\033[1;31;40m%s\033[0m" % ''''' 
  273. 注意事项:1、确认主库已经按照要求修改配置文件打开了bin-log,设置了相关参数 
  274.           2、确认从库已经安装和主库一样版本的mysql 
  275.           3、确认从库的配置文件注释掉了log-bin,否则从库导入数据库时会出错 
  276.           4、脚本运行过程中会清除从库/home/mysql/data/目录下面除mysql目录之外的所有目录和文件,有必要的话请做好备份 
  277.           5、运行之后删除/data1/目录下的压缩包 
  278.           6、运行格式:python create_slave.py 根据提示输入主库的内网地址 
  279.           7、从库创建完成并且数据与主库追齐之后要用脚本验证数据的一致性,数据一致后整个创建从库过程完成 
  280.           8、在执行check_mysql时,会出现Broken pipe的错误,这个是由于python调用系统命令关闭和打开mysql时显示的信息没有正确的显示在终端造成的,没有影响,暂时没有找到不让显示此类信息的方法,亟待解决 
  281. '''.decode("utf-8").encode("GBK"
  282.     find_ip() 
  283.     master_ip = raw_input('Enter :Mater_eth1_ip :'
  284.     boss = Database(master_ip) 
  285.     boss.check_mysql() 
  286.     boss.export_table() 
  287.     boss.down_back() 
  288.     boss.unbz2() 
  289.     boss.import_date() 
  290.     boss.restart_mysql() 
  291.     boss.slave_start() 

 

你可能感兴趣的:(mysql,python,自动创建,从库脚本)