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. PLSQL Package包的使用

    创建包头 create or replace package pak_kingsql is procedure pro_kingsql(p_one in varchar2,p_two out varc ...

  2. CF573C Bear and Drawing 构造+树论

    正解:构造 解题报告: 传送门! 这题首先可以画下图找下规律,,,然后通过找规律可以发现,最终的方案一定是一条主干+一些枝条,而且这些枝条的分杈一定小于等于2 明确一下主干的定义,最左边的节点和最右边 ...

  3. Memcached与redis的比较--stackoverflow(转)

    原文:http://blog.nosqlfan.com/html/3729.html 这两年Redis火得可以,Redis也常常被当作Memcached的挑战者被提到桌面上来.关于Redis与Memc ...

  4. AspNetPager.dll 分页控件使用

    今天在用.net 做网站的时候,用到了DATALIST,但是datalist 没有自带的分页控件,后来在网上找了好长时间,看了aspnetpager.dll这个控件,这个控件挺好用的.我把使用方法写出 ...

  5. Javascript异步执行时要小心的变量作用域

    function asyncFunction(callback){ setTimeout(function(){ callback() },200); } var color = 'blue'; // ...

  6. sql优化 慢查询分析

    查询速度慢的原因很多,常见如下几种 SQL慢查询分析 转自:https://www.cnblogs.com/firstdream/p/5899383.html 1.没有索引或者没有用到索引(这是查询慢 ...

  7. 全套 AR 应用设计攻略都在这里!

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/jILRvRTrc/article/details/79823908 通过将虚拟内容与现实世界融合,增 ...

  8. Django之分页功能

    Django提供了一个新的类来帮助你管理分页数据,这个类存放在django/core/paginator.py.它可以接收列表.元组或其它可迭代的对象. 基本语法 class Paginator(ob ...

  9. Locust性能测试3-no-web模式和csv报告保存

    前言 前面是在web页面操作,需要手动的点start启动,结束的时候也需要手工去点stop,没法自定义运行时间,这就不太方便. locust提供了命令行运行的方法,不启动web页面也能运行,这就是no ...

  10. iOS UI基础-3.0图片浏览器及plist使用

    需求: 1.显示当前图片序号/总图片数 2.显示图片 3.上一张图片.下一张图片转换 4.显示图片描述 下面用代码来实现 // // UYViewController.m // 3.0图片查看器 // ...