python创建MySQL多实例-1

前言

  • 什么是多实例

多实例就是允许在同一台机器上创建另外一套不同配置文件的数据库,他们之间是相互独立的,主要有以下特点,

  • 1》 不能同时使用一个端口
  • 2》 不可以使用同一个socket文件
  • 3》 也不可以使用同样的pid
  • 4》 配置文件也必须是不一样的
  • 5》 存入数据的data目录也不能一样
  • 6》 日志文件位置也不可以一样

上面这些只是我个人的一些理解,具体的可能参考网上的一些文章

https://www.percona.com/blog/2014/08/26/mysqld_multi-how-to-run-multiple-instances-of-mysql/

https://freedo.ga/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwjOr4-hj7LTAhXpiFQKHSKNDD4QFggrMAE&url=https%3A%2F%2Fdev.mysql.com%2Fdoc%2Fmysql%2Fen%2Fmultiple-servers.html&usg=AFQjCNGkZSDJbsHCVbm0n8cubpUha2SPsA

https://dev.mysql.com/doc/refman/en/multiple-windows-services.html

需求

通过python脚本来实现创建多个实例

使用方法

程序的目录结构如下

# tree mysql_tools/
mysql_tools/
├── library
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── mysql.py
│   └── mysql.pyc
└── manager
├── __init__.py
└── myman.py 2 directories, 6 files
# python myman.py  -h
Usage: myman.py [options] Options:
-h, --help show this help message and exit
-n NAME, --name=NAME
-p PORT, --port=PORT
-c COMMAND, --command=COMMAND

如创建一个my02.cnf的配置文件,端口为3302

python myman.py -n my02 -p 3302 -c create

实例目录结构

# tree -L 3 /data/mysql/
/data/mysql/
├── conf
│   ├── my01.cnf
│   └── my02.cnf
└── data
├── my01
│   ├── ibdata1
│   ├── ib_logfile0
│   ├── ib_logfile1
│   ├── my01-err.log
│   ├── my01.pid
│   ├── my01.sock
│   ├── mysql
│   └── test
└── my02
├── ibdata1
├── ib_logfile0
├── ib_logfile1
├── my02-err.log
├── my02.pid
├── my02.sock
├── mysql
└── test 8 directories, 14 files

源码如下

  • ./library/mysql.py
#!/usr/bin/env python
#-*- coding:utf8 -*- from ConfigParser import ConfigParser
import os class MySQLDConfig(ConfigParser):
def __init__(self, cfg, **kwargs):
ConfigParser.__init__(self, allow_no_value=True)
# super(ConfigParser, self).__init__(allow_no_value=True) # ConfigParser的你类是以传统方式定义的,所以这里不可以用super来重写方法
self.cfg = cfg
self.mysqld_vars = {} if os.path.exists(self.cfg):
self.config = cfg
self.read(self.config)
self.get_mysqld_vars()
else:
self.get_default_mysqld_vars() self.set_mysqld_vars(kwargs) def set_mysqld_vars(self, kwargs):
for k,v in kwargs.items():
setattr(self, k, v)
' add every k-v pairs to dictonary. '
self.mysqld_vars[k] = v def get_mysqld_vars(self):
result = {}
'return a list'
options = self.options('mysqld')
for opt in options:
result[opt] = self.get('mysqld', opt)
self.set_mysqld_vars(result) def get_default_mysqld_vars(self):
defaults = {
'user': 'mysql',
'port': '3307',
'socket': ' /var/lib/mysql/mysql.sock',
# 'skip-locking': None,
'key_buffer_size': '256M',
'max_allowed_packet': '1M',
'table_open_cache': '256',
'sort_buffer_size': '1M',
'read_buffer_size': '1M',
'read_rnd_buffer_size': '4M',
'myisam_sort_buffer_size': '64M',
'thread_cache_size': '8',
'query_cache_size': ' 16M',
}
' set default dict k-v to instance property. '
self.set_mysqld_vars(defaults) def set_vars(self, k, v):
self.mysqld_vars[k] = v ' set propertyis for non-supported name, e.g. "skip-slave-start" '
def save_default_cfg(self):
if not self.has_section('mysqld'):
self.add_section('mysqld') for k,v in self.mysqld_vars.items():
self.set('mysqld', k, v) with open(self.cfg, 'wb') as fd:
self.write(fd) if __name__ == '__main__':
cfg_file = '/tmp/my.cnf2'
mc = MySQLDConfig(cfg_file, max_connection=200, port=3307)
# mysqld_socket = mc.get('mysqld', 'socket')
# print mysqld_socket
mc.set_vars('skip-slave-start', None)
mc.save_default_cfg()
print mc.mysqld_vars['skip-slave-start']
print mc.max_connection
print mc.port
print mc.socket
  • ./library/mysql.py
#!/usr/bin/env python
#*-* coding: utf-8 -*- from optparse import OptionParser
import sys
import os
from subprocess import Popen,PIPE
import shlex
import time
import shutil current_dir = os.path.dirname(__file__)
parent_dir = os.path.join(current_dir, '../')
sys.path.append( os.path.abspath(parent_dir) ) from library.mysql import MySQLDConfig MYSQL_DATA_DIR = '/data/mysql/data'
MYSQL_CONF_DIR = '/data/mysql/conf' def opt():
parser = OptionParser()
parser.add_option('-n', '--name',
dest='name',
action='store',
default='myinstance'
)
parser.add_option('-p', '--port',
dest='port',
action='store',
default='3306'
)
parser.add_option('-c', '--command',
dest='command',
action='store',
default='check'
)
options, args = parser.parse_args() return options, args def _init():
if not os.path.exists(MYSQL_DATA_DIR):
# os.mkdir(MYSQL_DATA_DIR)
shutil.os.makedirs(MYSQL_DATA_DIR)
if not os.path.exists(MYSQL_CONF_DIR):
# os.mkdir(MYSQL_CONF_DIR)
shutil.os.makedirs(MYSQL_CONF_DIR) def readConfs():
from glob import glob
confs = glob(MYSQL_CONF_DIR + '/*.cnf')
return confs def checkPort(cfg_file, port):
mc = MySQLDConfig(cfg_file)
if mc.mysqld_vars['port'] == port:
return True
else:
return False def _genDict(name, port):
return {'pid-file': os.path.join(MYSQL_DATA_DIR, name, '%s.pid' % name),
'socket': os.path.join(MYSQL_DATA_DIR, name, '%s.sock' % name),
'port': port,
'datadir': os.path.join(MYSQL_DATA_DIR, name),
'log-error': os.path.join(MYSQL_DATA_DIR, name, '%s-err.log' % name)
} def getCnf(name):
return os.path.join(MYSQL_CONF_DIR, '%s.cnf' % name) def createInstance(name, port):
confs = readConfs() for conf in confs:
if conf.split('/')[-1].split('.')[0] == name:
print >> sys.stderr, 'Instance: %s is already exists' % name
sys.exit(-1)
if checkPort(conf, port):
print >> sys.stderr, 'Port: %s is already exists' % port
sys.exit(-1)
cnf = getCnf(name)
if not os.path.exists(cnf):
kwargs = _genDict(name, port)
mc = MySQLDConfig(cnf, **kwargs)
mc.save_default_cfg() datadir = os.path.join(MYSQL_DATA_DIR, name)
if not os.path.exists(datadir):
mysql_install(name)
setOwner(datadir)
mysqlRun(name) def mysql_install(name):
cnf = getCnf(name)
cmd = 'mysql_install_db --defaults-file=%s' % cnf
p = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
p.communicate()
p.returncode def setOwner(datadir):
os.system('chown mysql:mysql %s' % datadir) def mysqlRun(name):
cnf = getCnf(name)
cmd = 'mysqld_safe --defaults-file=%s &' % cnf
# 此行不知为什么会有问题,猜想可能与后台进程符号'&'有关
# p = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
# 如果是以后台进程启动的,那么就会hang住,因为后台进程并不会返回结果,所以p.communicate()就会一起处于等待状态
# p.communicate()
time.sleep(2)
p.returncode if __name__ == '__main__':
_init()
options, args = opt()
instance_name = options.name
instance_port = options.port
instance_cmd = options.command
createInstance(instance_name, instance_port)
# print options, args

python创建MySQL多实例-1的更多相关文章

  1. Python连接MySQL的实例代码

    Python连接MySQL的实例代码   MySQLdb下载地址:http://sourceforge.net/projects/mysql-python/ 下载解压缩后放到%Python_HOME% ...

  2. python3.4学习笔记(二十五) Python 调用mysql redis实例代码

    python3.4学习笔记(二十五) Python 调用mysql redis实例代码 #coding: utf-8 __author__ = 'zdz8207' #python2.7 import ...

  3. 一分钟在云端快速创建MySQL数据库实例

    本教程将帮助您了解如何使用Azure管理门户迅速创建,连接,配置MySQL 数据库 on Azure.完成本教程后,您将在Azure上拥有一个示例MySQL数据库服务器,并了解如何使用管理门户执行基本 ...

  4. python 创建mysql数据库

    昨天用shell脚本创建数据库,涉及java调用,比较折腾,改用python直接创建数据库,比较方便,好了,直接上代码,相关注释也添加了 # _*_encoding:UTF-8_*_import My ...

  5. 使用Python创建MySQL数据库实现字段动态添加以及动态的插入数据

    应用场景: 我们须要设计一个数据库来保存多个文档中每一个文档的keyword. 假如我们每一个文档字符都超过了1000,取当中出现频率最大的为我们的keyword. 如果每个文档的keyword都超过 ...

  6. python 创建类的实例对象

    # -*- coding: UTF-8 -*- class Employee: def __init__(self, name, salary): self.name = name self.sala ...

  7. python连接mysql数据库实例demo(银行管理系统数据库版)

    主函数: import adminView import os import pickle from bankFunction import BankFunction import time def ...

  8. Python操作MySQL数据库9个实用实例

    用python连接mysql的时候,需要用的安装版本,源码版本容易有错误提示.下边是打包了32与64版本. MySQL-python-1.2.3.win32-py2.7.exe MySQL-pytho ...

  9. Python 管理 MySQL

    Python MySQLdb 模块 Python pymysql 模块 Python SQLAlchemy 模块 Python ConfigParser 模块 Python 创建 MySQL 配置文件 ...

随机推荐

  1. Python面试基础篇

    1. 为什什么学习Python? Life is short, You need Python 2. 通过什什么途径学习的Python? pass 3. Python和Java.PHP.C.C#.C+ ...

  2. Linux IO多路复用之epoll网络编程及源码(转)

    原文: 前言 本章节是用基本的Linux基本函数加上epoll调用编写一个完整的服务器和客户端例子,可在Linux上运行,客户端和服务端的功能如下: 客户端从标准输入读入一行,发送到服务端 服务端从网 ...

  3. 008-插件方式启动web服务tomcat,jetty

    一.pom引入 1.tomcat7 <!-- tomcat7 --> <plugin> <groupId>org.apache.tomcat.maven</g ...

  4. Unity 脚本的执行顺序

    在Unity脚本中常用到的函数就是下面这些,他们的顺序也是按照箭头的方向执行的. Awake ->OnEable-> Start -> FixedUpdate-> Update ...

  5. qsv转换为mp4

    1:下载  装换工具:http://www.downza.cn/soft/27484.html 2:双击打开exe可执行程序. 3:添加要转换的文件,和转换后要存储的位置 4:开始转换,转换为flv格 ...

  6. PAT 1040 Longest Symmetric String[dp][难]

    1040 Longest Symmetric String (25)(25 分) Given a string, you are supposed to output the length of th ...

  7. Linux实验楼学习之一

    查看当前所在目录 pwd 创建文件:1-1.txt touch 1-1.txt 进入统计目录下的etc目录 cd /etc 强行终止当前程序 Ctrl + c 常用快捷键 按键 作用 Ctrl+d 键 ...

  8. [LeetCode] 312. Burst Balloons_hard tag: 区间Dynamic Programming

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

  9. Android弹性滑动的三种实现方式

    引言 上一篇文章我们介绍了实现弹性滑动的三种方式,但仅仅是给出了代码片段和方法理论.今天我们结合一个具体的例子来谈一下如何使用这三种方法来实现弹性滑动.今天我们的例子是仿IOS的下拉操作,我们知道An ...

  10. 转载如何实现portlet之间的传递参数

    Liferay 6开发学习(三十):跨页面Portlet之间的调用与数据传递 2014年10月09日 Liferay 评论 2 条 阅读 4,209 views 次 Portlet之间的通信方法有多种 ...