之前根据一个脚本文件,写了一个python的检测脚本。写的很久了,代码可以优化的地方有很多,不过还可以使用。
#!/usr/bin/env python import os import sys import time import string import re import pwd import subprocess import commands import getpass debug=0 text_color={ 'black':'\033[0m', 'boldblack':'\033[1;0m', 'red':'\033[31m', 'boldred':'\033[1;31m', 'green':'\033[32m', 'boldgreen':'\033[1;32m', 'yellow':'\033[33m', 'boldyellow':'\033[1;33m', 'blue':'\033[34m', 'boldblue':'\033[1;34m', 'magenta':'\033[35m', 'boldmagenta':'\033[1;35m', 'cyan':'\033[36m', 'boldcyan':'\033[1;36m', 'white':'\033[37m', 'boldwhite':'\033[1;37m' } ''' The Script for Log File.The Log File = "/var/log/message" ''' def log_func(msg): msg=str(msg) logfile=open("/var/log/mysql","a") logtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) ftime=("*** %-63s***" % logtime) logfile.write(ftime) logfile.write("\n") logfile.write(msg) logfile.write("\n") logfile.close() global logfile env = os._Environ(os.environ) logfile = env.get("LOGFILE") def execute_command(command_args,user=None,env=None): global logfile ret = -1 res = [] curdir = os.getcwd() if user is None: homedir = pwd.getpwuid(os.getuid())[5] else: try: int(user) homedir = pwd.getpwuid(int(user))[5] except: try: homedir = pwd.getpwnam(user)[5] except: homedir = pwd.getpwuid(os.getuid())[5] subproc_args = { 'stdin': subprocess.PIPE, 'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT, # 'shell': True, 'cwd': homedir, 'close_fds': True, } if env is not None: subproc_args['env'] = env if logfile is None: logfile = "/dev/null" logf = open(logfile, "a") try: pp = subprocess.Popen(command_args, **subproc_args) logf.write("Exec: '%s'\n" % (command_args)) except OSError: logf.write("Exec: '%s' failed.\n" % (command_args)) logf.close() return [ret,res] (stdouterr, stdin) = (pp.stdout, pp.stdin) while True: line = stdouterr.readline() ##logf.write(line) if not line: break line = line.rstrip() res.append(line) ret = pp.wait() logf.close() return [ret,res] ''' The Script for set color for print text on terminal ''' class setColor(object): def __init__(self): self.message="No message passed." self.color="black" def text_fun(self,message="No message passed.",color="black"): self.color=color self.msg=message try: os.system("tput sgr0") print text_color[self.color] print ("%s" % self.msg) os.system("tput sgr0") except Exception ,e: print ("%s" % self.msg) log_func(e) def text_banner(self): msg=''' ----------------------------------------------------- -- SElinux+ MYSQL Performance Tunning Script -- ----------------------------------------------------- -by qfong ''' self.text_fun(msg,"boldblue") def world_fun(self,message="No message passed.",color="black"): self.color=color self.msg=message try: os.system("tput sgr0") sys.stdout.write( text_color[self.color]) sys.stdout.write("%s" % self.msg) reset=os.popen('tput sgr0').read() sys.stdout.write(reset) except Exception ,e: print ("%s" % self.msg) log_func(e) global mysql count=0 info={ "user" : "root", "pwd": "", "host": "localhost", "port" : "3306" } class checkMysql(object): color=setColor() def __init__(self): pass def check_mysql_socket(self): socket=None (ret,res)=execute_command(["cat",".my.cnf"]) if ret == 0: cnf_socket_path=(re.findall(r"(?<=socket=).+?(?=')",str(res))) else: cnf_socket_path=None if cnf_socket_path: if not os.system("test -S %s" % (cnf_socket_path[0])): socket= cnf_socket_path elif not os.system("test -S /var/lib/mysql/mysql.sock"): socket="/var/lib/mysql/mysql.sock" elif not os.system("test -S /var/run/mysqld/mysqld.sock"): socket="/var/run/mysqld/mysqld.sock" elif not os.system("test -S /tmp/mysql.sock"): socket="/tmp/mysql.sock" else: status, output = commands.getstatusoutput("netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }' | head -1") if not status: output=0 socket=output if debug: print "Test for check_mysql_socket functions" print ("socket :%s" % socket) return socket def connect(self,pwd,user,port,host): if pwd: mysql = ("mysql -u%s -p%s -h%s -P%s" % (user,pwd,host,port)) else: mysql = ("mysql -u%s -h%s -P%s" % (user,host,port)) status, output = commands.getstatusoutput("%s -Bse \"SELECT SUBSTRING_INDEX(VERSION(), '.', +2)\"" % mysql) if not status: return True def inputpwd(self): try: user=raw_input('User[root]: ') inPassword=getpass.getpass('Password[Null]: ') port=raw_input('Port[3306]: ') host=raw_input('Host[localhost]: ') if not user : user='root' if not port : port='3306' if not host: host='localhost' if self.connect(inPassword,user,port,host): #print inPassword #return inPassword info['user']=user info['pwd']=inPassword info['host']=host info['port']=port else: self.inputpwd() except KeyboardInterrupt ,e: print e sys.exit(0) def mysql_connect(self): socket=self.check_mysql_socket() user_info={ "user" : "root", "pwd": "", "ipa": "localhost", "socket" : "socket" } #user_info['pwd']=''.join(self.inputpwd()) user_info['pwd']=info['pwd'] user_info['user']=info['user'] user_info['ipa']=info['host'] user_info['socket']=''.join(self.check_mysql_socket()) global mysql if user_info['pwd']: mysql = ("mysql -u%s -p%s -h%s -S%s" % (user_info['user'],user_info['pwd'],user_info['ipa'],user_info['socket'])) else: mysql = ("mysql -u%s -h%s -S%s" % (user_info['user'],user_info['ipa'],user_info['socket'])) return mysql def mysql_variable(self,parameter): status, output = commands.getstatusoutput("%s -Bse \"show /*!50000 global */ variables like %s\"|awk '{print $2}' " % (mysql,parameter)) if debug: print "Test for mysql_variable" print ("output:%s" % output) print ("status:%s" % status) if status == 0: return output def mysql_variableTab(self,parameter): status, output = commands.getstatusoutput("%s -Bse \"show /*!50000 global */ variables like %s\"|awk -F'\t' '{print $2}' " % (mysql,parameter)) if debug: print "Test for mysql_variableTAB" print ("output:%s" % output) print ("status:%s" % status) if status == 0: return output def mysql_status(self,parameter): status, output = commands.getstatusoutput("%s -Bse \"show /*!50000 global */ status like %s\"|awk -F'\t' '{print $2}' " % (mysql,parameter)) if debug: print "Test for mysql_status" print ("output:%s" % output) print ("status:%s" % status) if status == 0: return output ''' format time for human read ''' def forhumantime(self,time): day=int(time)/86400 hour=int(time)%86400/3600 minutes=int(time)%86400%3600/60 second=int(time)%86400%3600%60 return ("%s day %sh:%sm:%ss" % (day,hour,minutes,second)) if debug: print ("%s day %sh:%sm:%ss" % (day,hour,minutes,second)) def forhumansize(self,size): size=float(size) if size > 1073741824: util='G' level=3 elif size > 1048576: util='M' level=2 elif size > 1024: util='K' level=1 else : util='B' level=0 dividend=1 for i in range(0 ,level): dividend *= 1024 rsize =size/dividend return ("%4.2f %s" % (rsize,util)) def mysql_info(self): ''' mysql share info ''' mysql=self.mysql_connect() status, output = commands.getstatusoutput("%s -Bse \"SELECT SUBSTRING_INDEX(VERSION(), '.', +2)\"" % mysql) mysqlmajor_version=output status, output = commands.getstatusoutput("%s -Bse \"SELECT LEFT(REPLACE(SUBSTRING_INDEX(VERSION(), '-', +1), '.', ''),4)\"" % mysql) mysql_version_num=output ''' mysql base info ''' self.color.text_fun("-MySQL INFO:","boldblue") version=self.mysql_variable("\'version\'") self.color.world_fun("MySQL Version: %s \n" % version ) uptime=self.mysql_status("\'Uptime\'") rduptime=self.forhumantime(uptime) self.color.world_fun("Uptime = %s \n" % rduptime ) questions=self.mysql_status ("\'Questions\'") question_per_sec=int(questions)/int(uptime) self.color.world_fun("Avg. qps = %s \n" % question_per_sec) self.color.world_fun("Total Questions = %s \n" % questions) threads=self.mysql_status("\'Threads_connected\'") self.color.world_fun("Threads Connected = %s \n" % threads) if uptime < 172800: self.color.text_fun("Server has been running for over 48hrs.") else: self.color.text_fun("Warning: Server not been running for at least 48hrs.","boldred") ''' mysql SLOW QUERIES ''' self.color.text_fun("-MySQL SLOW QUERIES:","boldblue") slow_queries=self.mysql_status("\'Slow_queries\'") long_query_time=self.mysql_variable("\'long_query_time\'") log_slow_queries=self.mysql_variable("\'log%queries\'") if os.path.isfile("/etc/my.cnf"): if not log_slow_queries: status, output = commands.getstatusoutput("grep log_slow_queries /etc/my.cnf ") log_slow_queries=output if log_slow_queries == 'ON' : self.color.text_fun("The slow query log is enabled.") elif log_slow_queries == 'OFF': self.color.world_fun("The slow query log is") self.color.world_fun(" NOT ","boldred") self.color.world_fun("enabled.\n") elif not log_slow_queries: self.color.world_fun("The slow query log is") self.color.world_fun(" NOT ","boldred") self.color.world_fun("enabled.\n") else: self.color.text_fun(("Error:%s"% log_slow_queries),"boldred") self.color.world_fun('Current long_query_time =%s sec\n'% long_query_time) self.color.world_fun("You have ") self.color.world_fun(slow_queries,"boldred") self.color.world_fun(" out of ") self.color.world_fun(questions,"boldred") self.color.world_fun(" that take longer than %s sec. to complete\n" % long_query_time) prefered_query_time=5 if float(long_query_time) < float(prefered_query_time): self.color.text_fun(("Your long_query_time may be too high, I typically set this under %s sec" % prefered_query_time),"red") else: self.color.world_fun("Your long_query_time seems to be fine\n","green") if debug: print "Test for mysql slow queries" print ("log_slow_queries %s:" % log_slow_queries) self.color.world_fun(("Error:%s\n"% log_slow_queries),"boldred") ''' BINARY UPDATE LOG ''' self.color.text_fun("-MySQL BINARY UPDATE LOG:","boldblue") log_bin=self.mysql_variable("\'log_bin\'") max_binlog_size=self.mysql_variable("\'max_binlog_size\'") expire_logs_days=self.mysql_variable("\'expire_logs_days\'") sync_binlog=self.mysql_variable("\'sync_binlog\'") max_binlog_cache_size=self.mysql_variable("\'max_binlog_cache_size\'") if debug: print ("log_bin:%s" % log_bin) print ("max_binlog_size:%s" % max_binlog_size) print ("expire_logs_days:%s" % expire_logs_days) print ("sync_binlog:%s" % sync_binlog) print ("max_binlog_cache_size:%s" % max_binlog_cache_size) if log_bin == 'ON': self.color.world_fun("The binary update log is enabled\n") if expire_logs_days is None: self.color.text_fun("The max_binlog_size is not set. The binary log will rotate when it reaches 1GB","red") if expire_logs_days == '0': self.color.world_fun("The expire_logs_days is NOT set.\n","boldred") self.color.world_fun("The mysqld will retain the entire binary log until \n","red") self.color.world_fun("RESET MASTER or PURGE MASTER LOGS commands are run manually \n","red") self.color.world_fun("Setting expire_logs_days will allow you to remove old binary logs automatically \n","yellow") if sync_binlog == '0' : self.color.world_fun("Binlog sync is not enabled, you could loose binlog records during a server crash \n","red") else: self.color.world_fun("The binary update log is ") self.color.world_fun("NOT ","boldred") self.color.world_fun("enabled.\n") self.color.world_fun("You will not be able to do point in time recovery.\n","red") ''' MAX CONNECTIONS ''' self.color.text_fun("-MySQL MAX CONNECTIONS:","boldblue") max_connections=self.mysql_variable("\'max_connections\'") max_used_connections=self.mysql_status("\'Max_used_connections\'") threads_connected=self.mysql_status("\'Threads_connected\'") connections_ratio=float(max_used_connections)*100/float(max_connections) if debug: print ("max_connections : %s" % max_connections) print ("max_used_connections : %s" % max_used_connections) print ("threads_connected : %s" % threads_connected) print ("connections_ratio : %s" % connections_ratio) self.color.world_fun("Current max_connections = %s \n" % max_connections) self.color.world_fun("Current threads_connected = %s \n" % threads_connected) self.color.world_fun("Currentmax_used_connections = %s \n" % max_used_connections) self.color.world_fun("The number of used connections is ") text_color=None error='0' if int(connections_ratio) > 84: text_color="red" error='1' elif int(connections_ratio) < 16: text_color="red" error='2' else: text_color="green" error='0' #print text_color self.color.world_fun(("%4.2f%%" % connections_ratio),text_color) self.color.world_fun(" of the configured maximum.\n") if error=='1': self.color.world_fun("You should raise max_connections.\n",text_color) elif error=='2': self.color.world_fun("You are using less than 10% of your configured max_connections.\n",text_color) self.color.world_fun("Lowering max_connections could help to avoid an over-allocation of memory\n",text_color) self.color.world_fun("See \"MEMORY USAGE\" section to make sure you are not over-allocating\n",text_color) else: self.color.world_fun("Your max_connections variable seems to be fine.\n",text_color) text_color=None ''' WORKER THREADS ''' self.color.text_fun("-MySQL WORKER THREADS:","boldblue") threads_created1=self.mysql_status("\'Threads_connected\'") time.sleep(1) threads_created2=self.mysql_status("\'Threads_connected\'") threads_cached=self.mysql_status("\'Threads_cached\'") uptime=self.mysql_status("\'Uptime\'") thread_cache_size=self.mysql_variable("\'thread_cache_size\'") historic_threads_per_sec=float(threads_created1)/float(uptime) current_threads_per_sec=int(threads_created2)-int(threads_created1) self.color.world_fun("Current thread_cache_size = %s \n" % thread_cache_size) self.color.world_fun("Current threads_cached = %s \n" % threads_cached) self.color.world_fun("Current threads_per_sec = %s \n" % current_threads_per_sec) self.color.world_fun("Historic threads_per_sec = %4.2f \n" % historic_threads_per_sec) if int(historic_threads_per_sec) > 2 and int(threads_cached) < 1 : self.color.world_fun("Threads created per/sec are overrunning threads cached\n","red") elif int(historic_threads_per_sec) > 2: self.color.world_fun("Threads created per/sec are overrunning threads cached\n","red") self.color.world_fun("You should raise thread_cache_sized\n","red") else: self.color.world_fun("Your thread_cache_size is fine\n","green") if debug: print ("threads_created1 : %s" % threads_created1) print ("threads_created2 : %s" % threads_created2) print ("threads_cached : %s" % threads_cached) print ("uptime : %s" % uptime) print ("thread_cache_size : %s" % thread_cache_size) print ("historic_threads_per_sec : %s" % historic_threads_per_sec) print ("current_threads_per_sec : %s" % current_threads_per_sec) ''' KEY BUFFER ''' self.color.text_fun("-MySQL KEY BUFFER:","boldblue") key_read_requests=self.mysql_status("\'Key_read_requests\'") key_reads=self.mysql_status("\'Key_reads\'") key_blocks_used=self.mysql_status("\'Key_blocks_used\'") key_blocks_unused=self.mysql_status("\'Key_blocks_unused\'") key_cache_block_size=self.mysql_variable("\'key_cache_block_size\'") key_buffer_size=self.mysql_variable("\'key_buffer_size\'") datadir=self.mysql_variable("\'datadir\'") mysql_version_compile_machine=self.mysql_variable("\'version_compile_machine\'") #mysql="mysql" status, output = commands.getstatusoutput("%s -Bse \"/*!50000 SELECT IFNULL(SUM(INDEX_LENGTH),0) from information_schema.TABLES where ENGINE=\'MyISAM\' */ \" " % (mysql)) myisam_indexes=output if not myisam_indexes : status, output = commands.getstatusoutput("find %s -name '*.MYI' -exec du -b '{}' \; 2>&1 | awk '{ s += $1 } END { printf(\"%%.0f\\n\", s )}' " % (datadir)) myisam_indexes=output if key_reads == '0': self.color.world_fun("No key reads?!\n","boldred") self.color.world_fun("Seriously look into using some indexes\n","red") key_cache_miss_rate=0 key_buffer_free=float(key_blocks_unused)*float(key_cache_block_size)/float(key_buffer_size)*100 key_buffer_freeINT=int(key_buffer_free) else : key_cache_miss_rate=float(key_read_requests)/float(key_reads) if not key_blocks_unused: key_buffer_free=float(key_blocks_unused)*float(key_cache_block_size)/float(key_buffer_size)*100 key_buffer_freeINT=int(key_buffer_free) else: key_buffer_free='Unknown' key_buffer_freeINT=75 myisam_indexesHR=self.forhumansize(myisam_indexes); key_buffer_sizeHR=self.forhumansize(key_buffer_size); self.color.world_fun("Current MyISAM index space = %s \n" % myisam_indexesHR) self.color.world_fun("Current key_buffer_size = %s \n" % key_buffer_sizeHR) self.color.world_fun("Key cache miss rate is : %s \n" % key_cache_miss_rate) self.color.world_fun("Key buffer free ratio = %s \n" % key_buffer_freeINT) if mysqlmajor_version == '5.1' and int(mysql_version_num) < 5123: self.color.world_fun("Using key_buffer_size > 4GB will cause instability in versions prior to 5.1.23\n","boldred") if int(key_cache_miss_rate) <= 100 and int(key_cache_miss_rate) <= 0 and int(key_buffer_freeINT) <= 0 : self.color.world_fun("You could increase key_buffer_size\n","boldred") self.color.world_fun("It is safe to raise this up to 1/4 of total system memory;\n","red") self.color.world_fun("assuming this is a dedicated database server.\n","red") elif int(key_buffer_freeINT) <= 20 and int(key_buffer_size) <= int(myisam_indexes): self.color.world_fun("You could increase key_buffer_size\n","boldred") self.color.world_fun("It is safe to raise this up to 1/4 of total system memory;\n","red") self.color.world_fun("assuming this is a dedicated database server.\n","red") elif int(key_buffer_freeINT) <= 50 and int(key_cache_miss_rate) >= 10000 : self.color.world_fun("Your key_buffer_size seems to be too high;\n","boldred") self.color.world_fun("Perhaps you can use these resources elsewhere\n","red") else : self.color.world_fun("Your key_buffer_size seems to be fine.\n","green") if debug: print ("key_read_requests : %s" % key_read_requests) print ("key_reads : %s" % key_reads) print ("key_blocks_used : %s" % key_blocks_used) print ("key_blocks_unused : %s" % key_blocks_unused) print ("key_cache_block_size : %s" % key_cache_block_size) print ("key_buffer_size : %s" % key_buffer_size) print ("datadir : %s" % datadir) print ("mysql_version_compile_machine : %s" % mysql_version_compile_machine) print ("myisam_indexes : %s" % myisam_indexes) print ("key_cache_miss_rate : %s" % key_cache_miss_rate) print ("key_buffer_freeINT : %s" % key_buffer_freeINT) print ("myisam_indexesHR : %s" % myisam_indexesHR) print ("key_buffer_sizeHR : %s" % key_buffer_sizeHR) ''' QUERY CACHE ''' self.color.text_fun("-MySQL QUERY CACHE:","boldblue") mysql_version=self.mysql_variable("\'version\'") query_cache_size=self.mysql_variable("\'query_cache_size\'") query_cache_limit=self.mysql_variable("\'query_cache_limit\'") query_cache_min_res_unit=self.mysql_variable("\'query_cache_min_res_unit\'") qcache_free_memory=self.mysql_status("\'Qcache_free_memory\'") qcache_total_blocks=self.mysql_status("\'Qcache_total_blocks\'") qcache_free_blocks=self.mysql_status("\'Qcache_free_blocks\'") qcache_lowmem_prunes=self.mysql_status("\'Qcache_lowmem_prunes\'") if not query_cache_size: self.color.world_fun("You are using MySQL $mysql_version, no query cache is supported\n","red") elif query_cache_size == '0': self.color.world_fun("Query cache is supported but not enabled\n","red") else: qcache_used_memory=int(query_cache_size)-int(qcache_free_memory) qcache_mem_fill_ratio=float(qcache_used_memory)* 100 / float(query_cache_size) qcache_mem_fill_ratioINT=int(qcache_mem_fill_ratio) self.color.world_fun("Query cache is enabled\n","green") query_cache_sizeHR=self.forhumansize(query_cache_size) self.color.world_fun("Current query_cache_size = %s \n"% query_cache_sizeHR) qcache_used_memoryHR=self.forhumansize(qcache_used_memory) self.color.world_fun("Current query_cache_used = %s \n"% qcache_used_memoryHR) query_cache_limitHR=self.forhumansize(query_cache_limit) self.color.world_fun("Current query_cache_limit = %s \n"% query_cache_limitHR) self.color.world_fun("Query cache Memory fill ratio = %4.2f%% \n" % qcache_mem_fill_ratio) if not query_cache_min_res_unit: self.color.world_fun("No query_cache_min_res_unit is defined. Using MySQL < 4.1 cache fragmentation can be inpredictable\n","yellow") else: query_cache_min_res_unitHR=self.forhumansize(query_cache_min_res_unit) self.color.world_fun("Current query_cache_min_res_unit = %s \n" % query_cache_min_res_unitHR) if int(qcache_free_blocks) > 2 and int(qcache_total_blocks) < 0 : qcache_percent_fragmented=float(qcache_free_blocks)*100/float(qcache_total_blocks) qcache_percent_fragmentedINT=int(qcache_percent_fragmented) if int(qcache_percent_fragmentedINT) > 20 : self.color.world_fun(("Query Cache is %s%% fragmented \n" % qcache_percent_fragmentedINT),"red") self.color.world_fun("Run \"FLUSH QUERY CACHE\" periodically to defragment the query cache memor \n","red") self.color.world_fun("If you have many small queries lower 'query_cache_min_res_unit' to reduce fragmentation. \n" ,"red") if int(qcache_mem_fill_ratioINT) < 25 : self.color.world_fun("Your query_cache_size seems to be too high\n","red") self.color.world_fun("Perhaps you can use these resources elsewhere\n","red") if int(qcache_lowmem_prunes) >= 50 and qcache_mem_fill_ratioINT >= 80: self.color.world_fun("However,") self.color.world_fun(("%s " % qcache_lowmem_prunes ),"boldred") self.color.world_fun("queries have been removed from the query cache due to lack of memory \n") self.color.world_fun("Perhaps you should raise query_cache_size.\n","boldred") self.color.world_fun("MySQL won't cache query results that are larger than query_cache_limit in size.\n","yellow") if debug: print ("mysql_version : %s" % mysql_version) print ("query_cache_size : %s" % query_cache_size) print ("query_cache_limit : %s" % query_cache_limit) print ("query_cache_min_res_unit : %s" % query_cache_min_res_unit) print ("qcache_free_memory : %s" % qcache_free_memory) print ("qqcache_total_blocks : %s" % qcache_total_blocks) print ("qcache_free_blocks : %s" % qcache_free_blocks) print ("qcache_lowmem_prunes : %s" % qcache_lowmem_prunes) print ("qcache_used_memory : %s" % qcache_used_memory) print ("qcache_mem_fill_ratio : %s" % qcache_mem_fill_ratio) ''' SORT OPERATIONS ''' self.color.text_fun("-MySQL SORT OPERATIONS:","boldblue") sort_merge_passes=self.mysql_status("\'Sort_merge_passes\'") sort_scan=self.mysql_status("\'Sort_scan\'") sort_range=self.mysql_status("\'Sort_range\'") sort_buffer_size=self.mysql_variable("\'sort_buffer%\'") read_rnd_buffer_size=self.mysql_variable("\'read_rnd_buffer_size\'") total_sorts=int(sort_scan)+int(sort_range) if not read_rnd_buffer_size: read_rnd_buffer_size=self.mysql_variable("\'record_buffer\'") sort_buffer_size=int(sort_buffer_size)+8 read_rnd_buffer_size=int(read_rnd_buffer_size)+8 sort_buffer_sizeHR=self.forhumansize(sort_buffer_size) self.color.world_fun("Current sort_buffer_size = %s \n" % sort_buffer_sizeHR) read_rnd_buffer_sizeHR=self.forhumansize(read_rnd_buffer_size) self.color.world_fun("read_rnd_buffer_size = %s \n" % read_rnd_buffer_sizeHR) if int(total_sorts) == 0 : self.color.world_fun("No sort operations have been performed\n") passes_per_sort=0 if int(sort_merge_passes) != 0: passes_per_sort=float(sort_merge_passes)/float(total_sorts) else: passes_per_sort=0 if passes_per_sort >= 2: self.color.world_fun("On average") self.color.world_fun(passes_per_sort,"boldred") self.color.world_fun("sort merge passes are made per sort operation\n") self.color.world_fun("You should raise your sort_buffer_size read_rnd_buffer_size \n") else: self.color.world_fun("Sort buffer seems to be fine\n","green") if debug: print ("sort_merge_passes : %s" % sort_merge_passes) print ("sort_scan : %s" % sort_scan) print ("sort_range : %s" % sort_range) print ("sort_buffer_size : %s" % sort_buffer_size) print ("read_rnd_buffer_size : %s" % read_rnd_buffer_size) print ("total_sorts : %s" % total_sorts) print ("passes_per_sort : %s" % passes_per_sort) ''' JOINS ''' self.color.text_fun("-MySQL JOINS:","boldblue") select_full_join=self.mysql_status("\'Select_full_join\'") select_range_check=self.mysql_status("\'Select_range_check\'") join_buffer_size=self.mysql_variable("\'join_buffer%\'") join_buffer_size=int(join_buffer_size)+4096 join_buffer_sizeHR=self.forhumansize(join_buffer_size) self.color.world_fun("Current join_buffer_size = %s \n" % join_buffer_sizeHR) self.color.world_fun(("You have had %s queries where a join could not use an index properly \n" % select_full_join)) if int(select_range_check) == 0 and int(select_full_join) == 0: self.color.world_fun("Your joins seem to be using indexes properly \n","green") print_error=None raise_buffer=None if int(select_full_join) > 0 : print_error= 'true' raise_buffer= 'true' if int(select_range_check) > 0: self.color.world_fun(("You have had %s joins without keys that check for key usage after each row\n" % select_range_check),"green") print_error= 'true' raise_buffer= 'true' if int(join_buffer_size) > 4194304 : self.color.world_fun("join_buffer_size >= 4 M\nThis is not advised \n","boldred") if print_error : self.color.world_fun("hen look for non indexed joins in the slow query log \n","red") if print_error : self.color.world_fun("If you are unable to optimize your queries you may want to increase your join_buffer_size to accommodate larger joins in one pass\n","red") if debug: print ("select_full_join : %s" % select_full_join) print ("select_range_check : %s" % select_range_check) print ("join_buffer_size : %s" % join_buffer_size) print ("join_buffer_sizeHR : %s" % join_buffer_sizeHR) ''' TEMP TABLES ''' self.color.text_fun("-MySQL TEMP TABLES:","boldblue") created_tmp_tables=self.mysql_status("\'Created_tmp_tables\'") created_tmp_disk_tables=self.mysql_status("\'Created_tmp_disk_tables\'") tmp_table_size=self.mysql_variable("\'tmp_table_size\'") max_heap_table_size=self.mysql_variable("\'max_heap_table_size\'") if int(created_tmp_tables) == 0: tmp_disk_tables=0 else: tmp_disk_tables=float(created_tmp_disk_tables)*100/(int(created_tmp_tables)+int(created_tmp_disk_tables)) max_heap_table_sizeHR=self.forhumansize(max_heap_table_size) self.color.world_fun("Current max_heap_table_size = %s \n" % max_heap_table_sizeHR) tmp_table_sizeHR=self.forhumansize(tmp_table_size) self.color.world_fun("Current tmp_table_size = %s \n" % tmp_table_sizeHR) self.color.world_fun("Of %s temp tables, %4.2f%% were created on disk\n" % (created_tmp_tables,tmp_disk_tables)) if int(tmp_disk_tables) > int(max_heap_table_size): self.color.world_fun("Effective in-memory tmp_table_size is limited to max_heap_table_size.\n","yellow") if int(tmp_disk_tables) >= 25: self.color.world_fun("Perhaps you should increase your tmp_table_size and/or max_heap_table_size.\n","boldred") self.color.world_fun("to reduce the number of disk-based temporary tables\n","boldred") self.color.world_fun("Note! BLOB and TEXT columns are not allow in memory tables.\n","yellow") self.color.world_fun("If you are using these columns raising these values might not impact your\nratio of on disk temp tables.\n","yellow") else : self.color.world_fun("Created disk tmp tables ratio seems fine\n","green") if debug: print ("created_tmp_tables : %s" % created_tmp_tables) print ("created_tmp_disk_tables : %s" % created_tmp_disk_tables) print ("tmp_table_size : %s" % tmp_table_size) print ("max_heap_table_size : %s" % max_heap_table_size) print ("tmp_disk_tables : %s" % tmp_disk_tables) ''' OPEN FILES LIMIT ''' self.color.text_fun("-MySQL OPEN FILES LIMIT:","boldblue") open_files_limit=self.mysql_variable("\'open_files_limit\'") open_files=self.mysql_status("\'Open_files\'") if not open_files_limit or open_files_limit == 0: open_files_limit=os.popen("ulimit -n").read() cant_override=1 #print open_files_limit else: cant_override=0 self.color.world_fun("Current open_files_limit = %s \n" % open_files_limit) open_files_ratio=float(open_files)*100/float(open_files_limit) self.color.world_fun("The open_files_limit should typically be set to at least 2x-3x\n","yellow") self.color.world_fun("that of table_cache if you have heavy MyISAM usage.\n","yellow") if int(open_files_ratio) >= 75: self.color.world_fun("You currently have open more than 75% of your open_files_limit\n","boldred") if cant_override == '1': self.color.world_fun("You should set a higer value for ulimit -u in the mysql startup script then restart mysqld\n","boldred") elif cant_override == '0': self.color.world_fun("You should set a higher value for open_files_limit in my.cnf\n","boldred") else: self.color.world_fun("ERROR can't determine if mysqld override of ulimit is allowed\n","boldred") else: self.color.world_fun("Your open_files_limit value seems to be fine\n","green") if debug: print ("open_files_limit : %s" % open_files_limit) print ("open_files : %s" % open_files) print ("open_files_ratio : %s" % open_files_ratio) ''' TABLE CACHE ''' self.color.text_fun("-MySQL TABLE CACHE:","boldblue") datadir=self.mysql_variable("\'datadir\'") table_cache=self.mysql_variable("\'table_cache\'") table_open_cache=self.mysql_variable("\'table_open_cache\'") table_definition_cache=self.mysql_variable("\'table_definition_cache\'") open_tables=self.mysql_status("\'Open_tables\'") opened_tables=self.mysql_status("\'Opened_tables\'") open_table_definitions=self.mysql_status("\'Open_table_definitions\'") #mysql="mysql" status, output = commands.getstatusoutput("%s -Bse \"/*!50000 SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' */\"" % (mysql)) table_count=output if not table_count: table_count=os.popen("find $datadir 2>&1 | grep -c .frm$").read() if table_open_cache : table_cache=table_open_cache table_cache_hit_rate="unkowning" table_cache_fill="unkowning" if opened_tables != '0' and table_cache != 0 : table_cache_hit_rate = float(open_tables)*100/float(opened_tables) table_cache_fill=float(open_tables)*100/float(table_cache) elif opened_tables == '0' and table_cache != 0 : table_cache_hit_rate = 100 table_cache_fill=float(open_tables)*100/float(table_cache) else: self.color.world_fun("ERROR no table_cache ?!\n","boldred") if table_cache and not table_open_cache : self.color.world_fun("Current table_open_cache = %s tables \n" % table_cache) if table_cache : self.color.world_fun("Current table_open_cache = %s tables \n" % table_open_cache) self.color.world_fun("Current table_definition_cache = %s tables \n" % table_definition_cache) if table_count : self.color.world_fun("You have a total of %s tables \n" % table_count) if int(table_cache_fill) < 95: self.color.world_fun("You have ") self.color.world_fun(open_tables,"green") self.color.world_fun(" open tables \n") self.color.world_fun("The table_cache value seems to be fine \n","green") elif int(table_cache_hit_rate) <= 85 or int(table_cache_fill) >= 95 : self.color.world_fun("You have ") self.color.world_fun(open_tables,"boldred") self.color.world_fun(" open tables \n") self.color.world_fun("Current table_cache hit rate is ") self.color.world_fun(("%4.2f" % table_cache_hit_rate),"boldred") self.color.world_fun(", while ") self.color.world_fun(("%4.2f" % table_cache_fill),"boldred") self.color.world_fun(" of your table cache is in use\n") self.color.world_fun("You should probably increase your table_cache \n","red") else : self.color.world_fun("Current table_cache hit rate is ") self.color.world_fun(("%4.2f" % table_cache_hit_rate),"green") self.color.world_fun(", while ") self.color.world_fun(("%4.2f" % table_cache_fill),"green") self.color.world_fun(" of your table cache is in use\n") self.color.world_fun("The table cache value seems to be fine \n","green") if int(table_definition_cache) and int(table_definition_cache) <= int(table_count) and int(table_count) < 100 : self.color.world_fun("You should probably increase your table_definition_cache value. \n","red") if debug: print ("datadir : %s" % datadir) print ("table_cache : %s" % table_cache) print ("table_open_cache : %s" % table_open_cache) print ("table_definition_cache : %s" % table_definition_cache) print ("open_tables : %s" % open_tables) print ("opened_tables : %s" % opened_tables) print ("open_table_definitions : %s" % open_table_definitions) print ("table_count : %s" % table_count) print ("table_cache_hit_rate : %s" % table_cache_hit_rate) print ("table_cache_fill : %s" % table_cache_fill) ''' TABLE LOCKING ''' self.color.text_fun("-MySQL TABLE LOCKING:","boldblue") table_locks_waited=self.mysql_status("\'Table_locks_waited\'") table_locks_immediate=self.mysql_status("\'Table_locks_immediate\'") concurrent_insert=self.mysql_variable("\'concurrent_insert\'") low_priority_updates=self.mysql_variable("\'low_priority_updates\'") self.color.world_fun("Current Lock Wait ratio = ") if int(table_locks_waited) > 0 : immediate_locks_miss_rate = float(table_locks_immediate)/float(table_locks_waited) self.color.world_fun(("1 : %4.2f \n" % immediate_locks_miss_rate),"red") else : immediate_locks_miss_rate = 9999 self.color.world_fun(("0 : %s \n" % questions),"red") if int(immediate_locks_miss_rate) < 5000 : self.color.world_fun("You may benefit from selective use of InnoDB \n") if low_priority_updates == 'OFF': self.color.world_fun("If you have long running SELECT's against MyISAM tables and perform \nfrequent updates consider setting 'low_priority_updates=1' \n") if int(concurrent_insert) <= 1 and mysqlmajor_version == '5.0' or mysqlmajor_version == '5.1' : self.color.world_fun("If you have a high concurrency of inserts on Dynamic row-length tables \nonsider setting 'concurrent_insert=2' \n") else: self.color.world_fun("The table locking seems to be fine \n","green") if debug: print ("table_locks_waited : %s" % table_locks_waited) print ("table_locks_immediate : %s" % table_locks_immediate) print ("concurrent_insert : %s" % concurrent_insert) print ("low_priority_updates : %s" % low_priority_updates) ''' TABLE SCANS ''' self.color.text_fun("-MySQL TABLE SCANS:","boldblue") com_select=self.mysql_status("\'Com_select\'") read_rnd_next=self.mysql_status("\'Handler_read_rnd_next\'") read_buffer_size=self.mysql_variable("\'read_buffer_size\'") if not read_buffer_size : read_buffer_size=self.mysql_variable("\'record_buffer\'") read_buffer_sizeHR=self.forhumansize(read_buffer_size) self.color.world_fun("Current read_buffer_size = %s \n"% read_buffer_sizeHR) if int(com_select) > 0 : full_table_scans= float(read_rnd_next)/float(com_select) self.color.world_fun("Current table scan ratio = %4.2f : 1 \n"% full_table_scans) if int(full_table_scans) >= 4000 and int(read_buffer_size) <= 2097152 : self.color.world_fun("You have a high ratio of sequential access requests to SELECTs \n","red") self.color.world_fun("You may benefit from raising 'read_buffer_size' and/or improving your use of indexes \n","red") elif int(read_buffer_size) > 8388608 : self.color.world_fun("read_buffer_size is over 8 MB \n","red") self.color.world_fun("there is probably no need for such a large read_buffe\n","red") else: self.color.world_fun("read_buffer_size seems to be fine\n","green") else: self.color.world_fun("read_buffer_size seems to be fine\n","green") if debug: print ("com_select : %s" % com_select) print ("read_rnd_next : %s" % read_rnd_next) print ("read_buffer_size : %s" % read_buffer_size) ''' INNODB STATUS ''' self.color.text_fun("-MySQL INNODB STATUS:","boldblue") have_innodb=self.mysql_variable("\'have_innodb\'") if have_innodb == 'YES': innodb_buffer_pool_size=self.mysql_variable("\'innodb_buffer_pool_size\'") innodb_additional_mem_pool_size=self.mysql_variable("\'innodb_additional_mem_pool_size\'") innodb_fast_shutdown=self.mysql_variable("\'innodb_fast_shutdown\'") innodb_flush_log_at_trx_commit=self.mysql_variable("\'innodb_flush_log_at_trx_commit\'") innodb_locks_unsafe_for_binlog=self.mysql_variable("\'innodb_locks_unsafe_for_binlog\'") innodb_log_buffer_size=self.mysql_variable("\'innodb_log_buffer_size\'") innodb_log_file_size=self.mysql_variable("\'innodb_log_file_size\'") innodb_log_files_in_group=self.mysql_variable("\'innodb_log_files_in_group\'") innodb_safe_binlog=self.mysql_variable("\'innodb_safe_binlog\'") innodb_thread_concurrency=self.mysql_variable("\'innodb_thread_concurrency\'") status, output1 = commands.getstatusoutput("%s -Bse \"/*!50000 SELECT IFNULL(SUM(INDEX_LENGTH),0) from information_schema.TABLES where ENGINE='InnoDB' */\"" % (mysql)) innodb_indexes=output1 status, output2 = commands.getstatusoutput("%s -Bse \"/*!50000 SELECT IFNULL(SUM(DATA_LENGTH),0) from information_schema.TABLES where ENGINE='InnoDB' */\"" % (mysql)) innodb_data=output2 if innodb_indexes : innodb_buffer_pool_pages_data=self.mysql_status("\'Innodb_buffer_pool_pages_data\'") innodb_buffer_pool_pages_misc=self.mysql_status("\'Innodb_buffer_pool_pages_misc\'") innodb_buffer_pool_pages_free=self.mysql_status("\'Innodb_buffer_pool_pages_free\'") innodb_buffer_pool_pages_total=self.mysql_status("\'Innodb_buffer_pool_pages_total\'") innodb_buffer_pool_read_ahead_seq=self.mysql_status("\'Innodb_buffer_pool_read_ahead_seq\'") innodb_buffer_pool_read_requests=self.mysql_status("\'Innodb_buffer_pool_read_requests\'") innodb_os_log_pending_fsyncs=self.mysql_status("\'Innodb_os_log_pending_fsyncs\'") innodb_os_log_pending_writes=self.mysql_status("\'Innodb_os_log_pending_writes\'") innodb_log_waits=self.mysql_status("\'Innodb_log_waits\'") innodb_row_lock_time=self.mysql_status("\'Innodb_row_lock_time\'") innodb_row_lock_time=self.mysql_status("\'Innodb_row_lock_waits\'") innodb_indexesHR=self.forhumansize(innodb_indexes) self.color.world_fun("Current InnoDB index space = %s \n"% innodb_indexesHR) innodb_dataHR=self.forhumansize(innodb_data) self.color.world_fun("Current InnoDB data space = %s \n"% innodb_dataHR) percent_innodb_buffer_pool_free=float(innodb_buffer_pool_pages_free)*100/float(innodb_buffer_pool_pages_total) self.color.world_fun("Current InnoDB buffer pool free = %4.2f%%\n"% percent_innodb_buffer_pool_free) else: self.color.world_fun("Cannot parse InnoDB stats prior to 5.0.x\n","red") innodb_buffer_pool_sizeHR=self.forhumansize(innodb_buffer_pool_size) self.color.world_fun("Current innodb_buffer_pool_size = %s \n"% innodb_buffer_pool_sizeHR) self.color.world_fun("Depending on how much space your innodb indexes take up it may be safe\n") self.color.world_fun("to increase this value to up to 2 / 3 of total system memory\n") else: self.color.world_fun("No InnoDB Support Enabled!\n","boldred") if debug: print ("have_innodb : %s" % have_innodb ) print ("innodb_buffer_pool_size : %s" % innodb_buffer_pool_size ) print ("innodb_additional_mem_pool_size : %s" % innodb_additional_mem_pool_size ) print ("innodb_fast_shutdown : %s" % innodb_fast_shutdown ) print ("innodb_flush_log_at_trx_commit : %s" % innodb_flush_log_at_trx_commit) print ("innodb_locks_unsafe_for_binlog : %s" % innodb_locks_unsafe_for_binlog) print ("innodb_log_buffer_size : %s" % innodb_log_buffer_size ) print ("innodb_log_file_size : %s" % innodb_log_file_size ) print ("innodb_log_files_in_group : %s" % innodb_log_files_in_group) print ("innodb_thread_concurrency : %s" % innodb_thread_concurrency) print ("innodb_buffer_pool_pages_data : %s" % innodb_buffer_pool_pages_data ) print ("innodb_buffer_pool_pages_misc : %s" % innodb_buffer_pool_pages_misc ) print ("innodb_buffer_pool_pages_free : %s" % innodb_buffer_pool_pages_free) print ("innodb_buffer_pool_pages_total : %s" % innodb_buffer_pool_pages_total) print ("innodb_buffer_pool_read_ahead_seq : %s" % innodb_buffer_pool_read_ahead_seq ) print ("innodb_buffer_pool_read_requests : %s" % innodb_buffer_pool_read_requests) print ("innodb_os_log_pending_fsyncs : %s" % innodb_os_log_pending_fsyncs ) print ("innodb_os_log_pending_writes : %s" % innodb_os_log_pending_writes) print ("innodb_log_waits : %s" % innodb_log_waits ) print ("innodb_row_lock_time : %s" % innodb_row_lock_time) print ("innodb_row_lock_time : %s" % innodb_row_lock_time) ''' MEMORY USAGE ''' self.color.text_fun("-MySQL MEMORY USAGE:","boldblue") read_buffer_size=self.mysql_variable("\'read_buffer_size\'") read_rnd_buffer_size=self.mysql_variable("\'read_rnd_buffer_size\'") sort_buffer_size=self.mysql_variable("\'sort_buffer_size\'") thread_stack=self.mysql_variable("\'thread_stack\'") max_connections=self.mysql_variable("\'max_connections\'") join_buffer_size=self.mysql_variable("\'join_buffer_size\'") tmp_table_size=self.mysql_variable("\'tmp_table_size\'") max_heap_table_size=self.mysql_variable("\'max_heap_table_size\'") log_bin=self.mysql_variable("\'log_bin\'") max_used_connections=self.mysql_variable("\'Max_used_connections\'") if log_bin == 'ON': binlog_cache_size=self.mysql_variable("\'binlog_cache_size\'") else: binlog_cache_size=0 if int(max_heap_table_size) <= int(tmp_table_size): effective_tmp_table_size=max_heap_table_size else: effective_tmp_table_size=tmp_table_size per_thread_buffers=(int(read_buffer_size)+int(read_rnd_buffer_size)+int(sort_buffer_size)+int(thread_stack)+int(join_buffer_size)+int(binlog_cache_size))*int(max_connections) if not max_used_connections: max_used_connections=max_connections per_thread_max_buffers=(int(read_buffer_size)+int(read_rnd_buffer_size)+int(sort_buffer_size)+int(thread_stack)+int(join_buffer_size)+int(binlog_cache_size)) * int(max_used_connections) innodb_buffer_pool_size=self.mysql_variable("\'innodb_buffer_pool_size\'") if not innodb_buffer_pool_size: innodb_buffer_pool_size=0 innodb_additional_mem_pool_size=self.mysql_variable("\'innodb_additional_mem_pool_size\'") if not innodb_additional_mem_pool_size: innodb_additional_mem_pool_size=0 innodb_log_buffer_size=self.mysql_variable("\'innodb_log_buffer_size\'") if not innodb_log_buffer_size: innodb_log_buffer_size=0 key_buffer_size=self.mysql_variable("\'key_buffer_size\'") query_cache_size=self.mysql_variable("\'query_cache_size\'") if not query_cache_size: query_cache_size=0 global_buffers=int(innodb_buffer_pool_size)+int(innodb_additional_mem_pool_size)+int(innodb_log_buffer_size)+int(key_buffer_size)+int(query_cache_size) max_memory=int(global_buffers)+int(per_thread_max_buffers) total_memory=int(global_buffers)+int(per_thread_buffers) physical_memory=os.popen("awk '/^MemTotal/ { printf(\"%.0f\", $2*1024 ) }' < /proc/meminfo").read() pct_of_sys_mem=float(total_memory)*100/float(physical_memory) if int(pct_of_sys_mem) > 90 : perror=1 txt_color="boldred" else: txt_color="black" perror=0 #txt_color="boldred" max_memoryHR=self.forhumansize(max_memory) self.color.world_fun(("Max Memory Ever Allocated = %s \n"% max_memoryHR),txt_color) per_thread_buffersHR=self.forhumansize(per_thread_buffers) self.color.world_fun(("Configured Max Per-thread Buffers = %s \n"% per_thread_buffersHR),txt_color) global_buffersHR=self.forhumansize(global_buffers) self.color.world_fun(("Configured Max Global Buffers = %s \n"% global_buffersHR),txt_color) total_memoryHR=self.forhumansize(total_memory) self.color.world_fun(("Configured Max Memory Limit = %s \n"% total_memoryHR),txt_color) effective_tmp_table_sizeHR=self.forhumansize(effective_tmp_table_size) self.color.world_fun(("Plus %s per temporary table created \n"% effective_tmp_table_sizeHR),txt_color) physical_memoryHR=self.forhumansize(physical_memory) self.color.world_fun(("Physical Memory = %s \n"% physical_memoryHR),txt_color) if int(perror) == 1: self.color.world_fun("Max memory limit exceeds 90% of physical memory\n",txt_color) else: self.color.world_fun("Max memory limit seem to be within acceptable norms\n","green") if debug: print ("read_buffer_size : %s" % read_buffer_size ) print ("read_rnd_buffer_size : %s" % read_rnd_buffer_size ) print ("sort_buffer_size : %s" % sort_buffer_size ) print ("thread_stack : %s" % thread_stack ) print ("max_connections : %s" % max_connections ) print ("join_buffer_size : %s" % join_buffer_size ) print ("tmp_table_size : %s" % tmp_table_size ) print ("max_heap_table_size : %s" % max_heap_table_size) print ("log_bin : %s" % log_bin ) print ("max_used_connections : %s" % max_used_connections ) print ("innodb_buffer_pool_size : %s" % innodb_buffer_pool_size ) print ("innodb_additional_mem_pool_size : %s" % innodb_additional_mem_pool_size ) print ("innodb_log_buffer_size : %s" % innodb_log_buffer_size ) print ("key_buffer_size : %s" % key_buffer_size ) print ("query_cache_size : %s" % query_cache_size ) ''' ''' if __name__ == "__main__": app=setColor() app.text_banner() try: mysqlck=checkMysql() socket=mysqlck.check_mysql_socket() if not socket : app.world_fun("The mysqld process is not running or it is installed in a custom location.\n","boldred") sys.exit() except Exception,e: app.text_fun(e) try: mysqlck.mysql_info() #pass except Exception,e: app.text_fun(e) sys.exit(0)