加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

使用 python 管理 mysql 开发工具箱 - 1

发布时间:2021-07-06 06:09:42 所属栏目:大数据 来源: https://www.jb51.cc
导读:MysqL 是一个比较优秀的开源的数据库,很多公司都在使用。作为运维人员,经常做着一些重复性的工作,比如创建数据库实例,数据库备份等,完全都可以使用 python 编写一个工具来实现。 一、模块 ConfigParser 学习 ConfigParser 模块可以解析类似 MysqL 配置

MysqL 是一个比较优秀的开源的数据库,很多公司都在使用。作为运维人员,经常做着一些重复性的工作,比如创建数据库实例,数据库备份等,完全都可以使用 python 编写一个工具来实现。

一、模块 ConfigParser 学习

ConfigParser 模块可以解析类似 MysqL 配置文件 my.cnf 和 windows 下的 ini 配置文件。使用 ConfigParser 模块解析这类配置文件非常方便,而且可以增加、设置或删除配置文件的 section option 等,如果你使用 C 语言解析过配置文件,你就能明白 ConfigParser 模块的高效。

1. 使用前需要注意的

ConfigParser 模块在 python 2.6 版本中不支持没有 value 的 option 解析,解决的方法有 2 种:

(a) 升级 python 2.6 到 python 2.7。
(b) 拷贝一个 python 2.7 标准库的 ConfigParser.py 文件到 2.6 的标准库覆盖原来的 ConfigParser.py 文件。

推荐使用第一种方式,直接,一劳永逸;不过第二种方式比较简单。我用的是 CentOS 6,默认 python2.6.6,我升级 python 版本为 2.7.10。

参考我的一篇博文:http://www.cnblogs.com/liwei0526vip/p/6219998.html

2. ConfigParser 基本使用

导入模块并实例化

import ConfigParser
conf = ConfigParser.ConfigParser(allow_no_value=True)

读配置文件 read/readfp

In [3]: conf.read('/root/my.cnf')
Out[3]: []
# 返回配置文件列表,其实可以读取多个配置文件的列表,实际应用中没有意义,一般都只读取一个配置文件
# readfp() 函数可以读取 open() 函数返回的文件句柄 fp

section 相关操作

,MysqLdMysqLdumpMysqLmyisamchkMysqLhotcopy']
 判断是否有section [user]
In [15]: conf.has_section()
Out[15]: True

options 相关操作

In [16]: conf.options(')              列出options
In [17]: conf.set(keyvalue')    添加options [key] 同样可以修改options
In [18]: conf.remove_option(')  删除options
In [23]: conf.has_option( 判断是否有[key]

获取 get 值 value

In [24]: conf.get(port)
Out[24]: 3306'                              返回value字符串格式
In [25]: conf.getint()
Out[25]: 3306                                返回value整数格式
In [26]: conf.getfloat(xxxx')     返回value浮点数格式
In [27]: conf.getboolean(')   返回value布尔型格式
In [28]: conf.items()
Out[28]: 
[(),(query_cache_size16Mserver-id1')]

写入配置文件

3. 高级功能项

ConfigParser 模块中定义了3个类对配置文件进行操作。分别是 RawConfigParser、ConfigParser、SafeConfigParser。RawCnfigParser 是最基础的INI文件读取类,ConfigParser、SafeConfigParser支持对%(value)s变量的解析

>>> 设定配置文件 test.conf

[test] 
url = http://%(host)s:%(port)s/Portal 
host = localhost 
port = 8080

>>> 代码中使用ConfigParser解析:

>>> 终端输出内容:

http://localhost:8080/Portal
localhost:8080

SafeConfigParser 可以实现 ConfigParser 同样的功能。

?

二、生成 MysqL 配置文件模板

通过借助于 ConfigParser 模块,写了一个?MysqLDConfig 的工具类,使用这个类可以对 MysqL 配置文件进行一些列的操作:生成模板、添加选项、修改选项等,非常方便,作为后续开发工具箱的一个重要工具库。代码 MysqL.py 如下:

:41             socket/var/lib/MysqL/MysqL.sock42             key_buffer_size256M43             max_allowed_packet1M44             table_open_cache25645             sort_buffer_size46             read_buffer_size47             read_rnd_buffer_size4M48             myisam_sort_buffer_size64M49             thread_cache_size850             51             thread_concurrency52             ': 53         }
54         self.set_MysqLd_vars(defaults)
55 
56      特殊的接口 单独去设置/添加变量 比如skip-salve-start等不能通过变量传递的选项
57      set_vars(self,v):
58         self.MysqLd_vars[k] =59 
60      将所有的选项保存到配置文件,包括:新添加和更新的
61      save(self):
62         if not self.has_section():
63             self.add_section(64          self.MysqLd_vars.items():
65             self.set(66         with open(self.config,1)">) as fd:
67             self.write(fd)
68 
69 if __name__ == __main__70     mc = MysqLDConfig(/root/my1.cnf71     print mc.get('MysqLd','port')
72     print mc.max_connections
73     print mc.port
74     print mc.socket
75     
76     mc.set_vars('skip-slave-start',None)
77     mc.save()
78     print mc.port

三、创建 MysqL 实例

借助于上一章节编写的 MysqLDConfig 类,来创建 MysqL 实例,大概如下几个步骤:

  1. 生成配置文件
  2. 安装初始化 MysqL 实例
  3. 设置属主属组
  4. 启动 MysqL 运行

此时的代码结构:

├── library
│?? ├── __init__.py
│?? └── MysqL.py
└── MysqLmanager
    └── myman.py
2 directories,3 files

具体的主代码 myman.py 如下:


 15  MysqL实例的配置文件目录
 16 MysqL_CONF_DIR = /var/MysqLmanager/conf 17 
 18  设置选项参数
 19  opt():
 20     parser = OptionParser()
 21     parser.add_option(
 22         -n--name 指定实例的name
 23         dest    = name 24         action  = store 25         default = myinstance 26     )
 27  28         -p--port 指定端口
 29         dest    =  30         action  =  31         default =  32  33  34         -c--command create check and so on...
 35         dest    = command 36         action  =  37         default = check 38  39     options,args = parser.parse_args()
 40     return options,args
 41 
 42  初始化目录(如果不存在则创建)
 43  _init():
 44     not os.path.exists(MysqL_DATA_DIR):
 45         os.makedirs(MysqL_DATA_DIR)
 46      os.path.exists(MysqL_CONF_DIR):
 47         os.makedirs(MysqL_CONF_DIR)
 48 
 49  使用glob模块读取配置文件,返回配置文件列表(绝对路径)
 50  readConfs():
 51      glob
 52     confs = glob.glob(MysqL_CONF_DIR + /*.cnf 53      confs
 54 
 55  检查指定的配置文件中端口号是否与指定端口相同
 56  checkPort(conf_file,port):
 57     mc = MysqLDConfig(conf_file)
 58     if mc.MysqLd_vars['] == port:
 59          True
 60      61          False
 62 
 63  有些配置项的值由具体示例而定,将这些不定项设置为字典
 64  _genDict(name,1)"> 65      66         pid-file': os.path.join(MysqL_DATA_DIR,name,1)">%s.pid' % name),1)"> 67         /tmp/%s.sock name,1)"> 68         : port,1)"> 69         datadir: os.path.join(MysqL_DATA_DIR,name),1)"> 70         log-error%s.log 71     }
 72 
 73  通过配置文件名称->配置文件的绝对路径
 74  getCNF(name):
 75     cnf = os.path.join(MysqL_CONF_DIR,1)">%s.cnf name)
 76      cnf
 77 
 78  MysqL执行安装过程
 79  MysqL_install(name):
 80     cnf = getCNF(name)
 81     cmd = MysqL_install_db --defaults-file=%s 82     p = Popen(shlex.split(cmd),stdout=PIPE,stderr=PIPE)
 83     p.communicate()
 84     p.returncode
 85 
 86  为保险起见,设置MysqL实例数据目录的属主数组
 87  setOwner(datadir):
 88     os.system(chown MysqL:MysqL %s -R datadir)
 89 
 90  运行MysqL实例
 91  MysqL_run(name):
 92     cnf = 93     cmd = MysqLd_safe --defaults-file=%s & 94     p = Popen(cmd,stderr=PIPE,shell= 95     time.sleep(2)
 96  97 
 98  创建MysqL实例主函数,由create子命令触发调用
 99  createInstance(name,1)">100     exists_confs = readConfs()
101 
102      检查给定的端口号和名称是否已经使用
103     for conf  exists_confs:
104         if conf.split(/')[-1][:-4] == name:
105             print >> sys.stderr,1)">Instance: %s is exists name
106             sys.exit(-1107          checkPort(conf,1)">108             Port: %s is exists port
109             sys.exit(-1110 
111      1. 生成配置文件
112     cnf =113      os.path.exists(cnf):
114         c =115         mc = MysqLDConfig(cnf,1)">c)
116         mc.save()
117     datadir = os.path.join(MysqL_DATA_DIR,name)
118      os.path.exists(datadir):
119          2. 安装初始化MysqL实例
120         MysqL_install(name)
121          3. 设置属主属组
122         setOwner(datadir)
123          4. 启动MysqL运行
124         MysqL_run(name)
125         
126 
127 128     _init()
129     options,1)"> opt()
130     instance_name = options.name
131     instance_port = options.port
132     instance_cmd  = options.command
133     if instance_cmd == create: 
134         createInstance(instance_name,instance_port)

>>>> 扩展:实现几个简单使用功能

  1. 启动 MysqL 实例
  2. 关闭 MysqL 实例
  3. 重启 MysqL 实例

四、MysqLdb 模块的使用

1. 安装 MysqL-python

直接使用 yum 工具安装:

[root@MysqL ~]# yum install MysqL-python -y

2. 设置库路径

使用 rpm -ql MysqL-python 命令可以查看到默认安装 MysqLdb 库路径是:/usr/lib64/python2.6/site-packages 。如果没有升级 python 版本,可以正常使用,直接 import 即可。但是我升级了 python 2.7.10 ,默认 python 2.7 不会去旧版本路径下找库的,因此无法使用。解决办法有几种:

  1. 设置环境变量 PYTHONPATH
  2. 在 sys.path 追加路径
  3. 拷贝 MysqLdb 库目录到 Python2.7 路径下
  4. 添加 .pth 文件,添加路径

我这里使用的方式是第 4 种:

[root@MysqL site-packages]# pwd
/usr/local/python27/lib/python2.7/site-packages
[root@MysqL site-packages]# cat python26sitepackages.pth    # 添加 xxx.pth 文件,文件中设置第三方库路径
/usr/lib64/python2.6/site-packages
# *.pth文件名称随意,文件后缀一定要是.pth

3. 基本使用

)

 获取游标句柄
In [3]: cur = conn.cursor()

 执行sql语句
In [4]: cur.execute(show databases;)
Out[4]: 3L

 获取sql执行结果
In [5]: cur.fetchall()
Out[5]: ((information_schema

五、MysqL 配置文件检查(与内存)

MysqL 可以通过配置文件和数据库命令行方式去修改参数变量,经常会有这种情况,临时通过命令行手动修改了选项参数,比如最大连接数不够了,通过 set global max_connections=200 来临时设置了参数。但是下次重启 MysqL 又会从配置文件读取参数。现在可以通过开发的工具箱来读取配置文件和内存中的参数是否一致,如果不一致,考虑以内存中的值为准,写入配置文件。部分代码如下:

?????????????????????????????????
22  diffMyVariables(name):
23     cur = connMysqL(name)
24     vars = getMyVariables(cur)
25     cnf =26     mc =27      mc.MysqLd_vars.items():
28         k = k.replace(-_29         if k in vars and v != vars[k]:
30             print k,v,vars[k]
31 
32 33 34     options,1)">35     instance_name =36     instance_port =37     instance_cmd  =39         createInstance(instance_name,instance_port)
40     elif instance_cmd == 'check'41         diffMyVariables(instance_name)

命令执行:python myman.py -n my01 -p 3306 -c check

六、MysqL 配置文件调整(同步)

通过 check 命令找到了配置文件和内存中参数的不同,然后就可以通过 adjust 命令来调整一下配置文件,保持配置文件和内存的同步。实现代码如下:

try20             k = args[0]
21         except IndexError:
22             print Usage: -c adjust max_connections 300. At least 1 arg.23         24             v = args[126             v = None
27         setMyVariables(instance_name,v)

七、数据库 MysqL 主从复制介绍

1. MysqL 主节点设置步骤

  • 打开bin-log:log-bin = MysqL-bin
  • 设置server-id:server-id = 1
  • 创建主从账号:grant replication slave on *.* to 'slave'@'%' identified by '123456';

2. MysqL 从节点设置步骤

  • 设置server-id:server-id = 2(写入配置文件)
  • 设置master-host:master-host = 192.168.0.8(写入配置文件)
  • 设置master-port:master-port = 3306(写入配置文件)
  • 设置master-user:master-user = slave(写入配置文件)
  • 设置master-password:master-pass = 123456(写入配置文件)

注意:以上 master 开头的选项可以写入配置文件,但不建议写入配置文件,不安全。可以使用如下命令代替:

MysqL> change master to master_host = '192.168.0.8= 3306,master_user repl123456'

3. 先后运行 Mster 和 Slave 实例

先运行 master,后运行 slave。在从节点上运行命令查看:show slave statusG;

4. 其它选项

skip-slave-start:从库节点 slave 运行时,不会直接启动 slave 的主从复制
replicate-ignore-db:忽略某个数据库的同步复制,比如 MysqL 库,忽略,常容易出错

八、代码实现主库和从库创建

以下是继续使用 create 子命令来实现主从库的创建。

" % (REPLICATION_USER,REPLICATION_PASS)
 7     cur = 9 
10  代替配置文件,在slave上设置master相关信息
11  changeMaster(name,host,port,user,password):
12     sql = """change master to 
13              master_host = '%s',1)">14              master_port = %s,1)">15              master_user = '%s',1)">16              master_password = '%s'
17           """ % (host,password)
18 
19     cur =21 
23 24     options,1)">25     instance_name =26     instance_port =27     instance_cmd  =28     if instance_cmd == 'create' args:
30             createInstance(instance_name,1)">31         32             dbtype =33             serverid = args[134             MysqL_options = {: serverid}
35             if dbtype == 'master'36                 MysqL_options[log-bin'] = MysqL-bin37                 createInstance(instance_name,instance_port,1)">MysqL_options) 
38                 runsql(instance_name)
39             elif dbtype == 'slave'40                  5.5 版本以上不建议将master开头字段写入配置文件,其实低版本写入配置文件也是不妥当的
41                 MysqL_options['master-host'] = args[2]
42                 MysqL_options['master-port'] = args[3]
43                 MysqL_options['master-user'] = REPLICATION_USER
44                 MysqL_options['master-pass'] = REPLICATION_PASS
45                 MysqL_options[replicate-ignore-db'     设置忽略MysqL库
46                 MysqL_options[skip-slave-start'] = None           设置slave运行时不自动启动主从复制
47                 createInstance(instance_name,**MysqL_options)   按照从选项来创建实例
48                 host = args[2]     传入master的主机
49                 port = args[3]     传入master的端口
50                 user = REPLICATION_USER
51                 password = REPLICATION_PASS
52                  设置master信息
                changeMaster(instance_name,password) 
54     55 adjust57         58             k =59         60             61         62             v = args[163         64             v =65         setMyVariables(instance_name,courier'>创建主库:python myman.py -n master01 -p 3306 -c create master 1
创建从库:python myman.py -n slave01 ?-p 3307 -c create slave ?2 192.168.0.8 3306

九、备份 MysqL 数据库

数据库备份很重要,要制定好备份策略。部分代码如下:

执行命令:python myman.py -n master01 -c backup

十、MysqL 备份的恢复还原

通过 backup 命令备份后得到 sql 文件,在另一个 MysqL 实例中可以直接导入备份文件。但是如果 master 节点又有数据写入,那么导入sql后的节点和原来节点的数据是不一致的,缺少了后续的写入数据。在 master 导出 sql 文件后,记录 bin-log 文件和 log 位置,那么在从节点导入 sql 文件后,再次根据 bin-log 和 pos 来和 master 进行再次同步,那么,master 和 slave 就保持数据的同步了。具体代码如下:

 6                  master_port = %s,1)"> 7                  master_user = '%s',1)"> 8                  master_password = '%s'
 9               11         sql = 12                  master_password = '%s',1)">                 master_log_file = '%s',1)">17                  master_log_pos = %s
18               20     cur = 定义MysqL备份恢复主函数,参数需要指定备份的sql文件 
24 def restoreMysqL(name,sqlfile,1)">25      创建从实例 传入选项参数
26     createInstance(name,1)">kw)
27     cnf =28     mc =29     port = mc.MysqLd_vars[ 执行导入sql的shell命令
31     cmd = MysqL -h 127.0.0.1 -u root -P %s < %s32     p = Popen(cmd,1)">33     stdin,1)">34 35 
 定义内部正则过滤参数的功能函数,获取:master-log-file 和 master-log-pos
37  findPos(s):
 re
39     rlog = re.compile(rMASTER_LOG_FILE='(S+)'40     rpos = re.compile(rMASTER_LOG_POS=(d+)41     log = rlog.search(s)
42     pos = rpos.search(s)
43     if log and pos:
44         return log.group(1),pos.group(145     46          (None,None)
47 
48  读sql文件,返回log、pos
 getPos(sqlfile):
50     with open(sqlfile) as fd:
51         for line  fd:
52             log,pos = findPos(line)
53             54                  log,pos
56 :
57 58      ... 省略了中间部分代码 ...
59     ':      MysqL备份命令
60         backupMysqL(instance_name)
restore':     MysqL备份的恢复命令
62         server_id =63         master_host = args[164         master_port = args[265         sqlfile = args[366         MysqLd_options = {: server_id}
67         MysqLd_options['] =68         MysqLd_options[69          恢复固定sql内容(sql文件备份的内容)
70         restoreMysqL(instance_name,1)">MysqLd_options)
71         logfile,logpos = getPos(sqlfile)
72          指定log和pos,来配置slave激活master的主从复制(实现增量备份的恢复)
73         changeMaster(instance_name,master_host,master_port,REPLICATION_USER,REPLICATION_PASS,logpos)

测试实验过程:
>>> python myman.py -n master01 -p 3306 -c create master 1
>>> create database db1; create database db2; create database db3;
>>>?python myman.py -n master01 -p 3306 -c backup
>>> create database db4;
>>>?python myman.py -n slave01 -p 3307 -c restore 2 192.168.0.8 3306 /var/MysqLmanager/back/master01/2017-01-01.03:08:36.sql

测试结果:slave01 可以同步到 master01 两次的写入数据。

这篇篇幅太长了,另开一篇博文《使用 python 管理 mysql 开发工具箱 - 2》

---------- 本文结束 ----------

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读