python mysql 多主_python创建MySQL多实例-1

python创建MySQL多实例-1

前言

什么是多实例

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

1》 不能同时使用一个端口

2》 不可以使用同一个socket文件

3》 也不可以使用同样的pid

4》 配置文件也必须是不一样的

5》 存入数据的data目录也不能一样

6》 日志文件位置也不可以一样

需求

通过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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值