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 实例,大概如下几个步骤:
- 生成配置文件
- 安装初始化 MysqL 实例
- 设置属主属组
- 启动 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)
>>>> 扩展:实现几个简单使用功能
- 启动 MysqL 实例
- 关闭 MysqL 实例
- 重启 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 不会去旧版本路径下找库的,因此无法使用。解决办法有几种:
- 设置环境变量 PYTHONPATH
- 在 sys.path 追加路径
- 拷贝 MysqLdb 库目录到 Python2.7 路径下
- 添加 .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》
---------- 本文结束 ---------- (编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|