Advertisement
Guest User

MySQL Bash Tunner

a guest
May 6th, 2011
320
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 50.20 KB | None | 0 0
  1. #!/bin/sh
  2.  
  3. #########################################################################
  4. #                                   #
  5. #   MySQL performance tuning primer script              #
  6. #   Writen by: Matthew Montgomery <mmontgomery@mysql.com>       #
  7. #   Inspired by: MySQLARd (http://gert.sos.be/demo/mysqlar/)    #
  8. #   Version: 1.5-r5     Released: 2009-11-22            #
  9. #   Licenced under GPLv2                                            #
  10. #                                   #
  11. #########################################################################
  12.  
  13. #########################################################################
  14. #                                   #
  15. # Little known feature: 1st argument is execution mode          #
  16. #                                   #
  17. #   Usage: ./tuning-primer.sh [ mode ]              #
  18. #                                   #
  19. #   Available Modes:                        #
  20. #       all :       perform all checks (default)        #
  21. #       prompt :    prompt for login credintials and socket #
  22. #               and execution mode          #
  23. #       mem, memory :   run checks for tunable options which    #
  24. #               effect memory usage         #
  25. #       disk, file :    run checks for options which effect #
  26. #               i/o performance or file handle limits   #
  27. #       innodb :    run InnoDB checks /* to be improved */  #
  28. #       misc :      run checks for that don't categorise    #
  29. #               well Slow Queries, Binary logs,     #
  30. #               Used Connections and Worker Threads #
  31. #########################################################################
  32. #                                   #
  33. # Set this socket variable ONLY if you have multiple instances running  #
  34. # or we are unable to find your socket, and you don't want to to be #
  35. # prompted for input each time you run this script.         #
  36. #                                   #
  37. #########################################################################
  38. socket=
  39.  
  40.  
  41. export black='\033[0m'
  42. export boldblack='\033[1;0m'
  43. export red='\033[31m'
  44. export boldred='\033[1;31m'
  45. export green='\033[32m'
  46. export boldgreen='\033[1;32m'
  47. export yellow='\033[33m'
  48. export boldyellow='\033[1;33m'
  49. export blue='\033[34m'
  50. export boldblue='\033[1;34m'
  51. export magenta='\033[35m'
  52. export boldmagenta='\033[1;35m'
  53. export cyan='\033[36m'
  54. export boldcyan='\033[1;36m'
  55. export white='\033[37m'
  56. export boldwhite='\033[1;37m'
  57.  
  58.  
  59. cecho ()
  60.  
  61. ## -- Function to easliy print colored text -- ##
  62.  
  63.     # Color-echo.
  64.     # Argument $1 = message
  65.     # Argument $2 = color
  66. {
  67. local default_msg="No message passed."
  68.  
  69. message=${1:-$default_msg}  # Defaults to default message.
  70.  
  71. #change it for fun
  72. #We use pure names
  73. color=${2:-black}       # Defaults to black, if not specified.
  74.  
  75. case $color in
  76.     black)
  77.          printf "$black" ;;
  78.     boldblack)
  79.          printf "$boldblack" ;;
  80.     red)
  81.          printf "$red" ;;
  82.     boldred)
  83.          printf "$boldred" ;;
  84.     yellow)
  85.          printf "$yellow" ;;
  86.     boldyellow)
  87.          printf "$boldyellow" ;;
  88.     blue)
  89.          printf "$blue" ;;
  90.     boldblue)
  91.          printf "$boldblue" ;;
  92.     magenta)
  93.          printf "$magenta" ;;
  94.     boldmagenta)
  95.          printf "$boldmagenta" ;;
  96.     cyan)
  97.          printf "$cyan" ;;
  98.     boldcyan)
  99.          printf "$boldcyan" ;;
  100.     white)
  101.          printf "$white" ;;
  102.     boldwhite)
  103.          printf "$boldwhite" ;;
  104. esac
  105.   printf "%s\n"  "$message"
  106.   tput sgr0         # Reset to normal.
  107.   printf "$black"
  108.  
  109. return
  110. }
  111.  
  112.  
  113. cechon ()      
  114.  
  115. ## -- Function to easliy print colored text -- ##
  116.  
  117.     # Color-echo.
  118.     # Argument $1 = message
  119.     # Argument $2 = color
  120. {
  121. local default_msg="No message passed."
  122.                 # Doesn't really need to be a local variable.
  123.  
  124. message=${1:-$default_msg}  # Defaults to default message.
  125.  
  126. #change it for fun
  127. #We use pure names
  128. color=${2:-black}       # Defaults to black, if not specified.
  129.  
  130. case $color in
  131.     black)
  132.          printf "$black" ;;
  133.     boldblack)
  134.          printf "$boldblack" ;;
  135.     red)
  136.          printf "$red" ;;
  137.     boldred)
  138.          printf "$boldred" ;;
  139.     yellow)
  140.          printf "$yellow" ;;
  141.     boldyellow)
  142.          printf "$boldyellow" ;;
  143.     blue)
  144.          printf "$blue" ;;
  145.     boldblue)
  146.          printf "$boldblue" ;;
  147.     magenta)
  148.          printf "$magenta" ;;
  149.     boldmagenta)
  150.          printf "$boldmagenta" ;;
  151.     cyan)
  152.          printf "$cyan" ;;
  153.     boldcyan)
  154.          printf "$boldcyan" ;;
  155.     white)
  156.          printf "$white" ;;
  157.     boldwhite)
  158.          printf "$boldwhite" ;;
  159. esac
  160.   printf "%s"  "$message"
  161.   tput sgr0         # Reset to normal.
  162.   printf "$black"
  163.  
  164. return
  165. }
  166.  
  167.  
  168. print_banner () {
  169.  
  170. ## -- Banner -- ##
  171.  
  172. cecho " -- MYSQL PERFORMANCE TUNING PRIMER --" boldblue
  173. cecho "      - By: Matthew Montgomery -" black
  174.  
  175. }
  176.  
  177. ## -- Find the location of the mysql.sock file -- ##
  178.  
  179. check_for_socket () {
  180.     if [ -z "$socket" ] ; then
  181.         # Use ~/my.cnf version
  182.         if [ -f ~/.my.cnf ] ; then
  183.             cnf_socket=$(grep ^socket ~/.my.cnf | awk -F \= '{ print $2 }' | head -1)
  184.         fi
  185.         if [ -S "$cnf_socket" ] ; then
  186.             socket=$cnf_socket
  187.         elif [ -S /var/lib/mysql/mysql.sock ] ; then
  188.             socket=/var/lib/mysql/mysql.sock
  189.         elif [ -S /var/run/mysqld/mysqld.sock ] ; then
  190.             socket=/var/run/mysqld/mysqld.sock
  191.         elif [ -S /tmp/mysql.sock ] ; then
  192.             socket=/tmp/mysql.sock
  193.         else
  194.             if [ -S "$ps_socket" ] ; then
  195.             socket=$ps_socket
  196.             fi
  197.         fi
  198.     fi
  199.     if [ -S "$socket" ] ; then
  200.         echo UP > /dev/null
  201.     else
  202.         cecho "No valid socket file \"$socket\" found!" boldred
  203.         cecho "The mysqld process is not running or it is installed in a custom location." red
  204.         cecho "If you are sure mysqld is running, execute script in \"prompt\" mode or set " red
  205.         cecho "the socket= variable at the top of this script" red
  206.         exit 1
  207.     fi
  208. }
  209.  
  210.  
  211. check_for_plesk_passwords () {
  212.  
  213. ## -- Check for the existance of plesk and login using it's credentials -- ##
  214.  
  215.     if [ -f /etc/psa/.psa.shadow ] ; then
  216.             mysql="mysql -S $socket -u admin -p$(cat /etc/psa/.psa.shadow)"
  217.             mysqladmin="mysqladmin -S $socket -u admin -p$(cat /etc/psa/.psa.shadow)"
  218.     else
  219.             mysql="mysql"
  220.             mysqladmin="mysqladmin"
  221.             # mysql="mysql -S $socket"
  222.             # mysqladmin="mysqladmin -S $socket"
  223.     fi
  224. }
  225.  
  226. check_mysql_login () {
  227.  
  228. ## -- Test for running mysql -- ##
  229.  
  230.     is_up=$($mysqladmin ping 2>&1)
  231.     if [ "$is_up" = "mysqld is alive" ] ; then
  232.         echo UP > /dev/null
  233.         # echo $is_up
  234.     elif [ "$is_up" != "mysqld is alive" ] ; then
  235.         printf "\n"
  236.         cecho "Using login values from ~/.my.cnf"
  237.         cecho "- INITIAL LOGIN ATTEMPT FAILED -" boldred
  238.         if [ -z $prompted ] ; then
  239.         find_webmin_passwords
  240.         else
  241.             return 1
  242.         fi
  243.        
  244.     else
  245.         cecho "Unknow exit status" red
  246.         exit -1
  247.     fi
  248. }
  249.  
  250. final_login_attempt () {
  251.         is_up=$($mysqladmin ping 2>&1)
  252.         if [ "$is_up" = "mysqld is alive" ] ; then
  253.                 echo UP > /dev/null
  254.         elif [ "$is_up" != "mysqld is alive" ] ; then
  255.                 cecho "- FINAL LOGIN ATTEMPT FAILED -" boldred
  256.         cecho "Unable to log into socket: $socket" boldred
  257.                 exit 1
  258.         fi
  259. }
  260.  
  261. second_login_failed () {
  262.  
  263. ## -- create a ~/.my.cnf and exit when all else fails -- ##
  264.  
  265.     cecho "Could not auto detect login info!"
  266.     cecho "Found Sockets: $found_socks"
  267.     cecho "Using: $socket" red
  268.     read -p "Would you like to provide a different socket?: [y/N] " REPLY
  269.         case $REPLY in
  270.             yes | y | Y | YES)
  271.             read -p "Socket: " socket
  272.             ;;
  273.         esac
  274.     read -p "Do you have your login handy ? [y/N] : " REPLY
  275.     case $REPLY in
  276.         yes | y | Y | YES)
  277.         answer1='yes'
  278.         read -p "User: " user
  279.         read -rp "Password: " pass
  280.         if [ -z $pass ] ; then
  281.         export mysql="$mysql -S$socket -u$user"
  282.         export mysqladmin="$mysqladmin -S$socket -u$user"
  283.         else
  284.         export mysql="$mysql -S$socket -u$user -p$pass"
  285.         export mysqladmin="$mysqladmin -S$socket -u$user -p$pass"
  286.         fi
  287.         ;;
  288.         *)
  289.         cecho "Please create a valid login to MySQL"
  290.         cecho "Or, set correct values for  'user=' and 'password=' in ~/.my.cnf"
  291.         ;;
  292.     esac
  293.     cecho " "
  294.     read -p "Would you like me to create a ~/.my.cnf file for you? [y/N] : " REPLY
  295.         case $REPLY in
  296.             yes | y | Y | YES)
  297.         answer2='yes'
  298.         if [ ! -f ~/.my.cnf ] ; then
  299.             umask 077
  300.             printf "[client]\nuser=$user\npassword=$pass\nsocket=$socket" > ~/.my.cnf
  301.             if [ "$answer1" != 'yes' ] ; then
  302.                 exit 1
  303.             else
  304.                 final_login_attempt
  305.                 return 0
  306.             fi
  307.         else
  308.             printf "\n"
  309.             cecho "~/.my.cnf already exists!" boldred
  310.             printf "\n"
  311.             read -p "Replace ? [y/N] : " REPLY
  312.             if [ "$REPLY" = 'y' ] || [ "$REPLY" = 'Y' ] ; then
  313.             printf "[client]\nuser=$user\npassword=$pass\socket=$socket" > ~/.my.cnf
  314.                 if [ "$answer1" != 'yes' ] ; then
  315.                     exit 1
  316.                 else
  317.                     final_login_attempt
  318.                     return 0
  319.                 fi
  320.             else
  321.                 cecho "Please set the 'user=' and 'password=' and 'socket=' values in ~/.my.cnf"
  322.                 exit 1
  323.             fi
  324.         fi
  325.         ;;
  326.         *)
  327.         if [ "$answer1" != 'yes' ] ; then
  328.             exit 1
  329.         else
  330.             final_login_attempt
  331.             return 0
  332.         fi
  333.         ;;
  334.     esac
  335. }
  336.  
  337. find_webmin_passwords () {
  338.  
  339. ## -- populate the .my.cnf file using values harvested from Webmin -- ##
  340.  
  341.     cecho "Testing for stored webmin passwords:"
  342.     if [ -f /etc/webmin/mysql/config ] ; then
  343.         user=$(grep ^login= /etc/webmin/mysql/config | cut -d "=" -f 2)
  344.         pass=$(grep ^pass= /etc/webmin/mysql/config | cut -d "=" -f 2)
  345.         if [  $user ] && [ $pass ] && [ ! -f ~/.my.cnf  ] ; then
  346.             cecho "Setting login info as User: $user Password: $pass"
  347.             touch ~/.my.cnf
  348.             chmod 600 ~/.my.cnf
  349.             printf "[client]\nuser=$user\npassword=$pass" > ~/.my.cnf
  350.             cecho "Retrying login"
  351.             is_up=$($mysqladmin ping 2>&1)
  352.             if [ "$is_up" = "mysqld is alive"  ] ; then
  353.                 echo UP > /dev/null
  354.             else
  355.                 second_login_failed
  356.             fi
  357.         echo
  358.         else
  359.             second_login_failed
  360.         echo
  361.         fi
  362.     else
  363.     cecho " None Found" boldred
  364.         second_login_failed
  365.     fi
  366. }
  367.  
  368. #########################################################################
  369. #                                   #
  370. #  Function to pull MySQL status variable               #
  371. #                                   #
  372. #  Call using :                             #
  373. #   mysql_status \'Mysql_status_variable\' bash_dest_variable   #
  374. #                                   #
  375. #########################################################################
  376.  
  377. mysql_status () {
  378.     local status=$($mysql -Bse "show /*!50000 global */ status like $1" | awk '{ print $2 }')
  379.     export "$2"=$status
  380. }
  381.  
  382. #########################################################################
  383. #                                   #
  384. #  Function to pull MySQL server runtime variable           #
  385. #                                   #
  386. #  Call using :                             #
  387. #   mysql_variable \'Mysql_server_variable\' bash_dest_variable #
  388. #   - OR -                              #
  389. #   mysql_variableTSV \'Mysql_server_variable\' bash_dest_variable  #
  390. #                                   #
  391. #########################################################################
  392.  
  393. mysql_variable () {
  394.     local variable=$($mysql -Bse "show /*!50000 global */ variables like $1" | awk '{ print $2 }')
  395.     export "$2"=$variable
  396. }
  397. mysql_variableTSV () {
  398.         local variable=$($mysql -Bse "show /*!50000 global */ variables like $1" | awk -F \t '{ print $2 }')
  399.         export "$2"=$variable
  400. }
  401.  
  402. float2int () {
  403.         local variable=$(echo "$1 / 1" | bc -l)
  404.         export "$2"=$variable
  405. }
  406.  
  407. divide () {
  408.  
  409. # -- Divide two intigers -- #
  410.  
  411.     usage="$0 dividend divisor '$variable' scale"
  412.     if [ $1 -ge 1 ] ; then
  413.         dividend=$1
  414.     else
  415.         cecho "Invalid Dividend" red
  416.         echo $usage
  417.         exit 1
  418.     fi
  419.     if [ $2 -ge 1 ] ; then
  420.         divisor=$2
  421.     else
  422.         cecho "Invalid Divisor" red
  423.         echo $usage
  424.         exit 1
  425.     fi
  426.     if [ ! -n $3 ] ; then
  427.         cecho "Invalid variable name" red
  428.         echo $usage
  429.         exit 1
  430.     fi
  431.     if [ -z $4 ] ; then
  432.         scale=2
  433.     elif [ $4 -ge 0 ] ; then
  434.         scale=$4
  435.     else
  436.         cecho "Invalid scale" red
  437.         echo $usage
  438.         exit 1
  439.     fi
  440.     export $3=$(echo "scale=$scale; $dividend / $divisor" | bc -l)
  441. }
  442.  
  443. human_readable () {
  444.  
  445. #########################################################################
  446. #                                   #
  447. #  Convert a value in to human readable size and populate a variable    #
  448. #  with the result.                         #
  449. #                                   #
  450. #  Call using:                              #
  451. #   human_readable $value 'variable name' [ places of precision]    #
  452. #                                   #
  453. #########################################################################
  454.  
  455.     ## value=$1
  456.     ## variable=$2
  457.     scale=$3
  458.  
  459.     if [ $1 -ge 1073741824 ] ; then
  460.         if [ -z $3 ] ; then
  461.             scale=2
  462.         fi
  463.         divide $1 1073741824 "$2" $scale
  464.         unit="G"
  465.     elif [ $1 -ge 1048576 ] ; then
  466.         if [ -z $3 ] ; then
  467.             scale=0
  468.         fi
  469.         divide $1 1048576 "$2" $scale
  470.             unit="M"
  471.     elif [ $1 -ge 1024 ] ; then
  472.         if [ -z $3 ] ; then
  473.             scale=0
  474.         fi
  475.         divide $1 1024 "$2" $scale
  476.             unit="K"
  477.     else
  478.         export "$2"=$1
  479.             unit="bytes"
  480.     fi
  481.     # let "$2"=$HR
  482. }
  483.  
  484. human_readable_time () {
  485.  
  486. ########################################################################
  487. #                                      #
  488. #   Function to produce human readable time                        #
  489. #                                      #
  490. ########################################################################
  491.  
  492.     usage="$0 seconds 'variable'"
  493.     if [ -z $1 ] || [ -z $2 ] ; then
  494.         cecho $usage red
  495.         exit 1
  496.     fi
  497.     days=$(echo "scale=0 ; $1 / 86400" | bc -l)
  498.     remainder=$(echo "scale=0 ; $1 % 86400" | bc -l)
  499.     hours=$(echo "scale=0 ; $remainder / 3600" | bc -l)
  500.     remainder=$(echo "scale=0 ; $remainder % 3600" | bc -l)
  501.     minutes=$(echo "scale=0 ; $remainder / 60" | bc -l)
  502.     seconds=$(echo "scale=0 ; $remainder % 60" | bc -l)
  503.     export $2="$days days $hours hrs $minutes min $seconds sec"
  504. }
  505.  
  506. check_mysql_version () {
  507.  
  508. ## -- Print Version Info -- ##
  509.  
  510.     mysql_variable \'version\' mysql_version
  511.     mysql_variable \'version_compile_machine\' mysql_version_compile_machine
  512.    
  513. if [ "$major_version" = '3.23' ] || [ "$major_version" = '4.0' ] ; then
  514.     cecho "MySQL Version $mysql_version $mysql_version_compile_machine is EOL please upgrade to MySQL 4.1 or later" boldred
  515. else
  516.     cecho "MySQL Version $mysql_version $mysql_version_compile_machine"
  517. fi
  518.  
  519.  
  520. }
  521.  
  522. post_uptime_warning () {
  523.  
  524. #########################################################################
  525. #                                   #
  526. #  Present a reminder that mysql must run for a couple of days to   #
  527. #  build up good numbers in server status variables before these tuning #
  528. #  suggestions should be used.                      #
  529. #                                   #
  530. #########################################################################
  531.  
  532.     mysql_status \'Uptime\' uptime
  533.     mysql_status \'Threads_connected\' threads
  534.     queries_per_sec=$(($questions/$uptime))
  535.     human_readable_time $uptime uptimeHR
  536.  
  537.     cecho "Uptime = $uptimeHR"
  538.     cecho "Avg. qps = $queries_per_sec"
  539.     cecho "Total Questions = $questions"
  540.     cecho "Threads Connected = $threads"
  541.     echo
  542.  
  543.     if [ $uptime -gt 172800 ] ; then
  544.         cecho "Server has been running for over 48hrs."
  545.         cecho "It should be safe to follow these recommendations"
  546.     else
  547.         cechon "Warning: " boldred
  548.         cecho "Server has not been running for at least 48hrs." boldred
  549.         cecho "It may not be safe to use these recommendations" boldred
  550.  
  551.     fi
  552.     echo ""
  553.     cecho "To find out more information on how each of these" red
  554.     cecho "runtime variables effects performance visit:" red
  555.     if [ "$major_version" = '3.23' ] || [ "$major_version" = '4.0' ] || [ "$major_version" = '4.1' ] ; then
  556.     cecho "http://dev.mysql.com/doc/refman/4.1/en/server-system-variables.html" boldblue
  557.     elif [ "$major_version" = '5.0' ] || [ "$major_version" = '5.1' ] ; then
  558.     cecho "http://dev.mysql.com/doc/refman/$major_version/en/server-system-variables.html" boldblue
  559.     else
  560.     cecho "UNSUPPORTED MYSQL VERSION" boldred
  561.     exit 1
  562.     fi
  563.     cecho "Visit http://www.mysql.com/products/enterprise/advisors.html" boldblue
  564.     cecho "for info about MySQL's Enterprise Monitoring and Advisory Service" boldblue
  565. }
  566.  
  567. check_slow_queries () {
  568.  
  569. ## -- Slow Queries -- ##
  570.  
  571.     cecho "SLOW QUERIES" boldblue
  572.  
  573.     mysql_status \'Slow_queries\' slow_queries
  574.     mysql_variable \'long_query_time\' long_query_time
  575.     mysql_variable \'log%queries\' log_slow_queries
  576.    
  577.     prefered_query_time=5
  578.     if [ -e /etc/my.cnf ] ; then
  579.         if [ -z $log_slow_queries ] ; then
  580.             log_slow_queries=$(grep log-slow-queries /etc/my.cnf)
  581.         fi
  582.     fi
  583.  
  584.     if [ "$log_slow_queries" = 'ON' ] ; then
  585.         cecho "The slow query log is enabled."
  586.     elif [ "$log_slow_queries" = 'OFF' ] ; then
  587.         cechon "The slow query log is "
  588.         cechon "NOT" boldred
  589.         cecho " enabled."
  590.     elif [ -z $log_slow_queries ] ; then
  591.         cechon "The slow query log is "
  592.         cechon "NOT" boldred
  593.         cecho " enabled."
  594.     else
  595.         cecho "Error: $log_slow_queries" boldred
  596.     fi
  597.     cecho "Current long_query_time = $long_query_time sec."
  598.     cechon "You have "
  599.     cechon "$slow_queries" boldred
  600.     cechon " out of "
  601.     cechon "$questions" boldred
  602.     cecho " that take longer than $long_query_time sec. to complete"
  603.    
  604.     float2int long_query_time long_query_timeInt
  605.  
  606.     if [ $long_query_timeInt -gt $prefered_query_time ] ; then
  607.                 cecho "Your long_query_time may be too high, I typically set this under $prefered_query_time sec." red
  608.     else
  609.         cecho "Your long_query_time seems to be fine" green
  610.     fi
  611.  
  612. }
  613.  
  614. check_binary_log () {
  615.  
  616. ## -- Binary Log -- ##
  617.  
  618.     cecho "BINARY UPDATE LOG" boldblue
  619.  
  620.     mysql_variable \'log_bin\' log_bin
  621.     mysql_variable \'max_binlog_size\' max_binlog_size
  622.     mysql_variable \'expire_logs_days\' expire_logs_days
  623.     mysql_variable \'sync_binlog\' sync_binlog
  624.     #  mysql_variable \'max_binlog_cache_size\' max_binlog_cache_size
  625.  
  626.     if [ "$log_bin" = 'ON' ] ; then
  627.         cecho "The binary update log is enabled"
  628.         if [ -z "$max_binlog_size" ] ; then
  629.             cecho "The max_binlog_size is not set. The binary log will rotate when it reaches 1GB." red
  630.         fi
  631.         if [ "$expire_logs_days" -eq 0 ] ; then
  632.             cecho "The expire_logs_days is not set." boldred
  633.             cechon "The mysqld will retain the entire binary log until " red
  634.             cecho "RESET MASTER or PURGE MASTER LOGS commands are run manually" red
  635.             cecho "Setting expire_logs_days will allow you to remove old binary logs automatically"  yellow
  636.             cecho "See http://dev.mysql.com/doc/refman/$major_version/en/purge-master-logs.html" yellow
  637.         fi
  638.         if [ "$sync_binlog" = 0 ] ; then
  639.             cecho "Binlog sync is not enabled, you could loose binlog records during a server crash" red
  640.         fi
  641.     else
  642.         cechon "The binary update log is "
  643.         cechon "NOT " boldred
  644.         cecho "enabled."
  645.         cecho "You will not be able to do point in time recovery" red
  646.         cecho "See http://dev.mysql.com/doc/refman/$major_version/en/point-in-time-recovery.html" yellow
  647.     fi
  648. }
  649.  
  650. check_used_connections () {
  651.  
  652. ## -- Used Connections -- ##
  653.  
  654.     mysql_variable \'max_connections\' max_connections
  655.     mysql_status \'Max_used_connections\' max_used_connections
  656.     mysql_status \'Threads_connected\' threads_connected
  657.  
  658.     connections_ratio=$(($max_used_connections*100/$max_connections))
  659.  
  660.     cecho "MAX CONNECTIONS" boldblue
  661.     cecho "Current max_connections = $max_connections"
  662.     cecho "Current threads_connected = $threads_connected"
  663.     cecho "Historic max_used_connections = $max_used_connections"
  664.     cechon "The number of used connections is "
  665.     if [ $connections_ratio -ge 85 ] ; then
  666.         txt_color=red
  667.         error=1
  668.     elif [ $connections_ratio -le 10 ] ; then
  669.         txt_color=red
  670.         error=2
  671.     else
  672.         txt_color=green
  673.         error=0
  674.     fi
  675.     # cechon "$max_used_connections " $txt_color
  676.     # cechon "which is "
  677.     cechon "$connections_ratio% " $txt_color
  678.     cecho "of the configured maximum."
  679.  
  680.     if [ $error -eq 1 ] ; then
  681.         cecho "You should raise max_connections" $txt_color
  682.     elif [ $error -eq 2 ] ; then
  683.         cecho "You are using less than 10% of your configured max_connections." $txt_color
  684.         cecho "Lowering max_connections could help to avoid an over-allocation of memory" $txt_color
  685.         cecho "See \"MEMORY USAGE\" section to make sure you are not over-allocating" $txt_color
  686.     else
  687.         cecho "Your max_connections variable seems to be fine." $txt_color
  688.     fi
  689.     unset txt_color
  690. }
  691.  
  692. check_threads() {
  693.  
  694. ## -- Worker Threads -- ##
  695.  
  696.     cecho "WORKER THREADS" boldblue
  697.  
  698.     mysql_status \'Threads_created\' threads_created1
  699.     sleep 1
  700.     mysql_status \'Threads_created\' threads_created2
  701.  
  702.     mysql_status \'Threads_cached\' threads_cached
  703.     mysql_status \'Uptime\' uptime
  704.     mysql_variable \'thread_cache_size\' thread_cache_size
  705.  
  706.     historic_threads_per_sec=$(($threads_created1/$uptime))
  707.     current_threads_per_sec=$(($threads_created2-$threads_created1))
  708.  
  709.     cecho "Current thread_cache_size = $thread_cache_size"
  710.     cecho "Current threads_cached = $threads_cached"
  711.     cecho "Current threads_per_sec = $current_threads_per_sec"
  712.     cecho "Historic threads_per_sec = $historic_threads_per_sec"
  713.  
  714.     if [ $historic_threads_per_sec -ge 2 ] && [ $threads_cached -le 1 ] ; then
  715.         cecho "Threads created per/sec are overrunning threads cached" red
  716.         cecho "You should raise thread_cache_size" red
  717.     elif [ $current_threads_per_sec -ge 2 ] ; then
  718.         cecho "Threads created per/sec are overrunning threads cached" red
  719.         cecho "You should raise thread_cache_size" red
  720.     else
  721.         cecho "Your thread_cache_size is fine" green
  722.     fi
  723. }
  724.  
  725. check_key_buffer_size () {
  726.  
  727. ## -- Key buffer Size -- ##
  728.  
  729.     cecho "KEY BUFFER" boldblue
  730.  
  731.     mysql_status \'Key_read_requests\' key_read_requests
  732.     mysql_status \'Key_reads\' key_reads
  733.     mysql_status \'Key_blocks_used\' key_blocks_used
  734.     mysql_status \'Key_blocks_unused\' key_blocks_unused
  735.     mysql_variable \'key_cache_block_size\' key_cache_block_size
  736.     mysql_variable \'key_buffer_size\' key_buffer_size
  737.         mysql_variable \'datadir\' datadir
  738.         mysql_variable \'version_compile_machine\' mysql_version_compile_machine
  739.     myisam_indexes=$($mysql -Bse "/*!50000 SELECT IFNULL(SUM(INDEX_LENGTH),0) from information_schema.TABLES where ENGINE='MyISAM' */")
  740.  
  741.     if [ -z $myisam_indexes ] ; then
  742.         myisam_indexes=$(find $datadir -name '*.MYI' -exec du $duflags '{}' \; 2>&1 | awk '{ s += $1 } END { printf("%.0f\n", s )}')
  743.     fi
  744.  
  745.         if [ $key_reads -eq 0 ] ; then
  746.                 cecho "No key reads?!" boldred
  747.                 cecho "Seriously look into using some indexes" red
  748.                 key_cache_miss_rate=0
  749.                 key_buffer_free=$(echo "$key_blocks_unused * $key_cache_block_size / $key_buffer_size * 100" | bc -l )
  750.                 key_buffer_freeRND=$(echo "scale=0; $key_buffer_free / 1" | bc -l)
  751.         else
  752.                 key_cache_miss_rate=$(($key_read_requests/$key_reads))
  753.                 if [ ! -z $key_blocks_unused ] ; then
  754.             key_buffer_free=$(echo "$key_blocks_unused * $key_cache_block_size / $key_buffer_size * 100" | bc -l )
  755.                     key_buffer_freeRND=$(echo "scale=0; $key_buffer_free / 1" | bc -l)
  756.                 else
  757.                         key_buffer_free='Unknown'
  758.                         key_buffer_freeRND=75
  759.                 fi
  760.         fi
  761.  
  762.     human_readable $myisam_indexes myisam_indexesHR
  763.     cecho "Current MyISAM index space = $myisam_indexesHR $unit"
  764.  
  765.     human_readable  $key_buffer_size key_buffer_sizeHR
  766.     cecho "Current key_buffer_size = $key_buffer_sizeHR $unit"
  767.     cecho "Key cache miss rate is 1 : $key_cache_miss_rate"
  768.     cecho "Key buffer free ratio = $key_buffer_freeRND %"
  769.  
  770.     if [ "$major_version" = '5.1' ] && [ $mysql_version_num -lt '5123' ] ; then
  771.         if [ $key_buffer_size -ge 4294967296 ] && ( echo "x86_64 ppc64 ia64 sparc64 i686" | grep -q $mysql_version_compile_machine ) ; then
  772.             cecho "Using key_buffer_size > 4GB will cause instability in versions prior to 5.1.23 " boldred
  773.             cecho "See Bug#5731, Bug#29419, Bug#29446" boldred
  774.         fi
  775.     fi
  776.     if [ "$major_version" = '5.0' ] && [ $mysql_version_num -lt '5052' ] ; then
  777.         if [ $key_buffer_size -ge 4294967296 ] && ( echo "x86_64 ppc64 ia64 sparc64 i686" | grep -q $mysql_version_compile_machine ) ; then
  778.             cecho "Using key_buffer_size > 4GB will cause instability in versions prior to 5.0.52 " boldred
  779.             cecho "See Bug#5731, Bug#29419, Bug#29446" boldred
  780.         fi
  781.     fi
  782.     if [ "$major_version" = '4.1' -o "$major_version" = '4.0' ] && [ $key_buffer_size -ge 4294967296 ] && ( echo "x86_64 ppc64 ia64 sparc64 i686" | grep -q $mysql_version_compile_machine ) ; then
  783.         cecho "Using key_buffer_size > 4GB will cause instability in versions prior to 5.0.52 " boldred
  784.         cecho "Reduce key_buffer_size to a safe value" boldred
  785.         cecho "See Bug#5731, Bug#29419, Bug#29446" boldred
  786.     fi
  787.  
  788.     if [ $key_cache_miss_rate -le 100 ] && [ $key_cache_miss_rate -gt 0 ] && [ $key_buffer_freeRND -le 20 ]; then
  789.         cecho "You could increase key_buffer_size" boldred
  790.         cecho "It is safe to raise this up to 1/4 of total system memory;"
  791.         cecho "assuming this is a dedicated database server."
  792.     elif [ $key_buffer_freeRND -le 20 ] && [ $key_buffer_size -le $myisam_indexes ] ; then
  793.         cecho "You could increase key_buffer_size" boldred
  794.         cecho "It is safe to raise this up to 1/4 of total system memory;"
  795.         cecho "assuming this is a dedicated database server."
  796.     elif [ $key_cache_miss_rate -ge 10000 ] || [ $key_buffer_freeRND -le 50  ] ; then
  797.         cecho "Your key_buffer_size seems to be too high." red
  798.         cecho "Perhaps you can use these resources elsewhere" red
  799.     else
  800.         cecho "Your key_buffer_size seems to be fine" green
  801.     fi
  802. }
  803.  
  804. check_query_cache () {
  805.  
  806. ## -- Query Cache -- ##
  807.  
  808.     cecho "QUERY CACHE" boldblue
  809.  
  810.     mysql_variable \'version\' mysql_version
  811.     mysql_variable \'query_cache_size\' query_cache_size
  812.     mysql_variable \'query_cache_limit\' query_cache_limit
  813.     mysql_variable \'query_cache_min_res_unit\' query_cache_min_res_unit
  814.     mysql_status \'Qcache_free_memory\' qcache_free_memory
  815.     mysql_status \'Qcache_total_blocks\' qcache_total_blocks
  816.     mysql_status \'Qcache_free_blocks\' qcache_free_blocks
  817.     mysql_status \'Qcache_lowmem_prunes\' qcache_lowmem_prunes
  818.  
  819.     if [ -z $query_cache_size ] ; then
  820.         cecho "You are using MySQL $mysql_version, no query cache is supported." red
  821.         cecho "I recommend an upgrade to MySQL 4.1 or better" red
  822.     elif [ $query_cache_size -eq 0 ] ; then
  823.         cecho "Query cache is supported but not enabled" red
  824.         cecho "Perhaps you should set the query_cache_size" red
  825.     else
  826.         qcache_used_memory=$(($query_cache_size-$qcache_free_memory))
  827.         qcache_mem_fill_ratio=$(echo "scale=2; $qcache_used_memory * 100 / $query_cache_size" | bc -l)
  828.         qcache_mem_fill_ratioHR=$(echo "scale=0; $qcache_mem_fill_ratio / 1" | bc -l)
  829.  
  830.         cecho "Query cache is enabled" green
  831.         human_readable $query_cache_size query_cache_sizeHR
  832.         cecho "Current query_cache_size = $query_cache_sizeHR $unit"
  833.         human_readable $qcache_used_memory qcache_used_memoryHR
  834.         cecho "Current query_cache_used = $qcache_used_memoryHR $unit"
  835.         human_readable $query_cache_limit query_cache_limitHR
  836.         cecho "Current query_cache_limit = $query_cache_limitHR $unit"
  837.         cecho "Current Query cache Memory fill ratio = $qcache_mem_fill_ratio %"
  838.         if [ -z $query_cache_min_res_unit ] ; then
  839.             cecho "No query_cache_min_res_unit is defined.  Using MySQL < 4.1 cache fragmentation can be inpredictable" %yellow
  840.         else
  841.             human_readable $query_cache_min_res_unit query_cache_min_res_unitHR
  842.             cecho "Current query_cache_min_res_unit = $query_cache_min_res_unitHR $unit"
  843.         fi
  844.         if [ $qcache_free_blocks -gt 2 ] && [ $qcache_total_blocks -gt 0 ] ; then
  845.             qcache_percent_fragmented=$(echo "scale=2; $qcache_free_blocks * 100 / $qcache_total_blocks" | bc -l)
  846.             qcache_percent_fragmentedHR=$(echo "scale=0; $qcache_percent_fragmented / 1" | bc -l)
  847.             if [ $qcache_percent_fragmentedHR -gt 20 ] ; then
  848.                 cecho "Query Cache is $qcache_percent_fragmentedHR % fragmented" red
  849.                 cecho "Run \"FLUSH QUERY CACHE\" periodically to defragment the query cache memory" red
  850.                 cecho "If you have many small queries lower 'query_cache_min_res_unit' to reduce fragmentation." red
  851.             fi
  852.         fi
  853.  
  854.         if [ $qcache_mem_fill_ratioHR -le 25 ] ; then
  855.                     cecho "Your query_cache_size seems to be too high." red
  856.                     cecho "Perhaps you can use these resources elsewhere" red
  857.         fi
  858.         if [ $qcache_lowmem_prunes -ge 50 ] && [ $qcache_mem_fill_ratioHR -ge 80 ]; then
  859.             cechon "However, "
  860.             cechon "$qcache_lowmem_prunes " boldred
  861.             cecho "queries have been removed from the query cache due to lack of memory"
  862.             cecho "Perhaps you should raise query_cache_size" boldred
  863.         fi
  864.         cecho "MySQL won't cache query results that are larger than query_cache_limit in size" yellow
  865.     fi
  866.  
  867. }
  868.  
  869. check_sort_operations () {
  870.  
  871. ## -- Sort Operations -- ##
  872.  
  873.     cecho "SORT OPERATIONS" boldblue
  874.  
  875.     mysql_status \'Sort_merge_passes\' sort_merge_passes
  876.     mysql_status \'Sort_scan\' sort_scan
  877.     mysql_status \'Sort_range\' sort_range
  878.     mysql_variable \'sort_buffer%\' sort_buffer_size
  879.     mysql_variable \'read_rnd_buffer_size\' read_rnd_buffer_size
  880.  
  881.     total_sorts=$(($sort_scan+$sort_range))
  882.     if [ -z $read_rnd_buffer_size ] ; then
  883.         mysql_variable \'record_buffer\' read_rnd_buffer_size
  884.     fi
  885.  
  886.     ## Correct for rounding error in mysqld where 512K != 524288 ##
  887.     sort_buffer_size=$(($sort_buffer_size+8))
  888.     read_rnd_buffer_size=$(($read_rnd_buffer_size+8))
  889.  
  890.     human_readable $sort_buffer_size sort_buffer_sizeHR
  891.     cecho "Current sort_buffer_size = $sort_buffer_sizeHR $unit"
  892.  
  893.     human_readable $read_rnd_buffer_size read_rnd_buffer_sizeHR
  894.     cechon "Current "
  895.     if [ "$major_version" = '3.23' ] ; then
  896.         cechon "record_rnd_buffer "
  897.     else
  898.         cechon "read_rnd_buffer_size "
  899.     fi
  900.     cecho "= $read_rnd_buffer_sizeHR $unit"
  901.  
  902.     if [ $total_sorts -eq 0 ] ; then
  903.         cecho "No sort operations have been performed"
  904.         passes_per_sort=0
  905.     fi
  906.     if [ $sort_merge_passes -ne 0 ] ; then
  907.         passes_per_sort=$(($sort_merge_passes/$total_sorts))
  908.     else
  909.         passes_per_sort=0
  910.     fi
  911.  
  912.     if [ $passes_per_sort -ge 2 ] ; then
  913.         cechon "On average "
  914.         cechon "$passes_per_sort " boldred
  915.         cecho "sort merge passes are made per sort operation"
  916.         cecho "You should raise your sort_buffer_size"
  917.         cechon "You should also raise your "
  918.         if [ "$major_version" = '3.23' ] ; then
  919.             cecho "record_rnd_buffer_size"
  920.         else
  921.             cecho "read_rnd_buffer_size"
  922.         fi
  923.     else
  924.         cecho "Sort buffer seems to be fine" green
  925.     fi
  926. }
  927.  
  928. check_join_operations () {
  929.  
  930. ## -- Joins -- ##
  931.  
  932.     cecho "JOINS" boldblue
  933.  
  934.     mysql_status \'Select_full_join\' select_full_join
  935.     mysql_status \'Select_range_check\' select_range_check
  936.     mysql_variable \'join_buffer%\' join_buffer_size
  937.    
  938.     ## Some 4K is dropped from join_buffer_size adding it back to make sane ##
  939.     ## handling of human-readable conversion ##
  940.  
  941.     join_buffer_size=$(($join_buffer_size+4096))
  942.  
  943.     human_readable $join_buffer_size join_buffer_sizeHR 2
  944.  
  945.     cecho "Current join_buffer_size = $join_buffer_sizeHR $unit"
  946.     cecho "You have had $select_full_join queries where a join could not use an index properly"
  947.  
  948.     if [ $select_range_check -eq 0 ] && [ $select_full_join -eq 0 ] ; then
  949.         cecho "Your joins seem to be using indexes properly" green
  950.     fi
  951.     if [ $select_full_join -gt 0 ] ; then
  952.         print_error='true'
  953.         raise_buffer='true'
  954.     fi
  955.     if [ $select_range_check -gt 0 ] ; then
  956.         cecho "You have had $select_range_check joins without keys that check for key usage after each row" red
  957.         print_error='true'
  958.         raise_buffer='true'
  959.     fi
  960.  
  961.     ## For Debuging ##
  962.     # print_error='true'
  963.     if [ $join_buffer_size -ge 4194304 ] ; then
  964.         cecho "join_buffer_size >= 4 M" boldred
  965.         cecho "This is not advised" boldred
  966.         raise_buffer=
  967.     fi
  968.  
  969.     if [ $print_error ] ; then
  970.         if [ "$major_version" = '3.23' ] || [ "$major_version" = '4.0' ] ; then
  971.             cecho "You should enable \"log-long-format\" "
  972.         elif [ "$major_version" = '4.1' ] || [ "$major_version" = '5.0' ] || [ "$major_version" = '5.1' ] ; then
  973.             cecho "You should enable \"log-queries-not-using-indexes\""
  974.         fi
  975.         cecho "Then look for non indexed joins in the slow query log."
  976.         if [ $raise_buffer ] ; then
  977.         cecho "If you are unable to optimize your queries you may want to increase your"
  978.         cecho "join_buffer_size to accommodate larger joins in one pass."
  979.         printf "\n"
  980.         cecho "Note! This script will still suggest raising the join_buffer_size when" boldred
  981.         cecho "ANY joins not using indexes are found." boldred
  982.         fi
  983.     fi
  984.  
  985.     # XXX Add better tests for join_buffer_size XXX #
  986. }
  987.  
  988. check_tmp_tables () {
  989.  
  990. ## -- Temp Tables -- ##
  991.  
  992.     cecho "TEMP TABLES" boldblue
  993.  
  994.     mysql_status \'Created_tmp_tables\' created_tmp_tables
  995.     mysql_status \'Created_tmp_disk_tables\' created_tmp_disk_tables
  996.     mysql_variable \'tmp_table_size\' tmp_table_size
  997.     mysql_variable \'max_heap_table_size\' max_heap_table_size
  998.  
  999.  
  1000.     if [ $created_tmp_tables -eq 0 ] ; then
  1001.         tmp_disk_tables=0
  1002.     else
  1003.         tmp_disk_tables=$((created_tmp_disk_tables*100/(created_tmp_tables+created_tmp_disk_tables)))
  1004.     fi
  1005.     human_readable $max_heap_table_size max_heap_table_sizeHR
  1006.     cecho "Current max_heap_table_size = $max_heap_table_sizeHR $unit"
  1007.  
  1008.     human_readable $tmp_table_size tmp_table_sizeHR
  1009.     cecho "Current tmp_table_size = $tmp_table_sizeHR $unit"
  1010.  
  1011.     cecho "Of $created_tmp_tables temp tables, $tmp_disk_tables% were created on disk"
  1012.     if [ $tmp_table_size -gt $max_heap_table_size ] ; then
  1013.         cecho "Effective in-memory tmp_table_size is limited to max_heap_table_size." yellow
  1014.     fi
  1015.     if [ $tmp_disk_tables -ge 25 ] ; then
  1016.         cecho "Perhaps you should increase your tmp_table_size and/or max_heap_table_size" boldred
  1017.         cecho "to reduce the number of disk-based temporary tables" boldred
  1018.         cecho "Note! BLOB and TEXT columns are not allow in memory tables." yellow
  1019.         cecho "If you are using these columns raising these values might not impact your " yellow
  1020.         cecho  "ratio of on disk temp tables." yellow
  1021.     else
  1022.         cecho "Created disk tmp tables ratio seems fine" green
  1023.     fi
  1024. }
  1025.  
  1026. check_open_files () {
  1027.  
  1028. ## -- Open Files Limit -- ##
  1029.     cecho "OPEN FILES LIMIT" boldblue
  1030.  
  1031.     mysql_variable \'open_files_limit\' open_files_limit
  1032.     mysql_status   \'Open_files\' open_files
  1033.    
  1034.     if [ -z $open_files_limit ] || [ $open_files_limit -eq 0 ] ; then
  1035.         open_files_limit=$(ulimit -n)
  1036.         cant_override=1
  1037.     else
  1038.         cant_override=0
  1039.     fi
  1040.     cecho "Current open_files_limit = $open_files_limit files"
  1041.    
  1042.     open_files_ratio=$(($open_files*100/$open_files_limit))
  1043.  
  1044.     cecho "The open_files_limit should typically be set to at least 2x-3x" yellow
  1045.     cecho "that of table_cache if you have heavy MyISAM usage." yellow
  1046.     if [ $open_files_ratio -ge 75 ] ; then
  1047.         cecho "You currently have open more than 75% of your open_files_limit" boldred
  1048.         if [ $cant_override -eq 1 ] ; then
  1049.             cecho "You should set a higer value for ulimit -u in the mysql startup script then restart mysqld" boldred
  1050.             cecho "MySQL 3.23 users : This is just a guess based upon the current shell's ulimit -u value" yellow
  1051.         elif [ $cant_override -eq 0 ] ; then
  1052.             cecho "You should set a higher value for open_files_limit in my.cnf" boldred
  1053.         else
  1054.             cecho "ERROR can't determine if mysqld override of ulimit is allowed" boldred
  1055.             exit 1
  1056.         fi
  1057.     else
  1058.         cecho "Your open_files_limit value seems to be fine" green
  1059.     fi
  1060.  
  1061.    
  1062.  
  1063. }
  1064.  
  1065. check_table_cache () {
  1066.  
  1067. ## -- Table Cache -- ##
  1068.  
  1069.     cecho "TABLE CACHE" boldblue
  1070.  
  1071.     mysql_variable \'datadir\' datadir
  1072.     mysql_variable \'table_cache\' table_cache
  1073.  
  1074.     ## /* MySQL +5.1 version of table_cache */ ##
  1075.     mysql_variable \'table_open_cache\' table_open_cache
  1076.     mysql_variable \'table_definition_cache\' table_definition_cache
  1077.  
  1078.     mysql_status \'Open_tables\' open_tables
  1079.     mysql_status \'Opened_tables\' opened_tables
  1080.     mysql_status \'Open_table_definitions\' open_table_definitions
  1081.  
  1082.     table_count=$($mysql -Bse "/*!50000 SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' */")
  1083.  
  1084.     if [ -z "$table_count" ] ; then
  1085.         if [ "$UID" != "$socket_owner" ] && [ "$UID" != "0" ] ; then
  1086.             cecho "You are not '$socket_owner' or 'root'" red
  1087.             cecho "I am unable to determine the table_count!" red
  1088.         else
  1089.             table_count=$(find $datadir 2>&1 | grep -c .frm$)
  1090.         fi
  1091.     fi
  1092.     if [ $table_open_cache ] ; then
  1093.         table_cache=$table_open_cache
  1094.     fi
  1095.  
  1096.     if [ $opened_tables -ne 0 ] && [ $table_cache -ne 0 ] ; then
  1097.         table_cache_hit_rate=$(($open_tables*100/$opened_tables))
  1098.         table_cache_fill=$(($open_tables*100/$table_cache))
  1099.     elif [ $opened_tables -eq 0 ] && [ $table_cache -ne 0 ] ; then
  1100.         table_cache_hit_rate=100
  1101.         table_cache_fill=$(($open_tables*100/$table_cache))
  1102.     else
  1103.         cecho "ERROR no table_cache ?!" boldred
  1104.         exit 1
  1105.     fi
  1106.     if [ $table_cache ] && [ ! $table_open_cache ] ; then
  1107.         cecho "Current table_cache value = $table_cache tables"
  1108.     fi
  1109.     if [ $table_open_cache ] ; then
  1110.         cecho "Current table_open_cache = $table_open_cache tables"
  1111.         cecho "Current table_definition_cache = $table_definition_cache tables"
  1112.     fi
  1113.     if [ $table_count ] ; then
  1114.     cecho "You have a total of $table_count tables"
  1115.     fi
  1116.  
  1117.     if  [ $table_cache_fill -lt 95 ] ; then
  1118.         cechon "You have "
  1119.         cechon "$open_tables " green
  1120.         cecho "open tables."
  1121.         cecho "The table_cache value seems to be fine" green
  1122.     elif [ $table_cache_hit_rate -le 85 -o  $table_cache_fill -ge 95 ]; then
  1123.         cechon "You have "
  1124.         cechon "$open_tables " boldred
  1125.         cecho "open tables."
  1126.         cechon "Current table_cache hit rate is "
  1127.         cecho "$table_cache_hit_rate%" boldred
  1128.         cechon ", while "
  1129.         cechon "$table_cache_fill% " boldred
  1130.         cecho "of your table cache is in use"
  1131.         cecho "You should probably increase your table_cache" red
  1132.     else
  1133.         cechon "Current table_cache hit rate is "
  1134.         cechon "$table_cache_hit_rate%" green
  1135.         cechon ", while "
  1136.         cechon "$table_cache_fill% " green
  1137.         cecho "of your table cache is in use"
  1138.         cecho "The table cache value seems to be fine" green
  1139.     fi
  1140.     if [ $table_definition_cache ] && [ $table_definition_cache -le $table_count ] && [ $table_count -ge 100 ] ; then
  1141.         cecho "You should probably increase your table_definition_cache value." red
  1142.     fi
  1143. }
  1144.  
  1145. check_table_locking () {
  1146.  
  1147. ## -- Table Locking -- ##
  1148.  
  1149.     cecho "TABLE LOCKING" boldblue
  1150.  
  1151.     mysql_status \'Table_locks_waited\' table_locks_waited
  1152.     mysql_status \'Table_locks_immediate\' table_locks_immediate
  1153.     mysql_variable \'concurrent_insert\' concurrent_insert
  1154.     mysql_variable \'low_priority_updates\' low_priority_updates
  1155.         if [ "$concurrent_insert" = 'ON' ]; then
  1156.                 concurrent_insert=1
  1157.         elif [ "$concurrent_insert" = 'OFF' ]; then
  1158.                 concurrent_insert=0
  1159.         fi
  1160.  
  1161.     cechon "Current Lock Wait ratio = "
  1162.     if [ $table_locks_waited -gt 0 ]; then
  1163.         immediate_locks_miss_rate=$(($table_locks_immediate/$table_locks_waited))
  1164.         cecho "1 : $immediate_locks_miss_rate" red
  1165.     else
  1166.         immediate_locks_miss_rate=99999 # perfect
  1167.         cecho "0 : $questions"
  1168.     fi
  1169.     if [ $immediate_locks_miss_rate -lt 5000 ] ; then
  1170.         cecho "You may benefit from selective use of InnoDB."
  1171.         if [ "$low_priority_updates" = 'OFF' ] ; then
  1172.         cecho "If you have long running SELECT's against MyISAM tables and perform"
  1173.         cecho "frequent updates consider setting 'low_priority_updates=1'"
  1174.         fi
  1175.         if [ $concurrent_insert -le 1 ] && [ "$major_version" = '5.0' -o "$major_version" = '5.1' ] ; then
  1176.         cecho "If you have a high concurrency of inserts on Dynamic row-length tables"
  1177.         cecho "consider setting 'concurrent_insert=2'."
  1178.         fi
  1179.     else
  1180.         cecho "Your table locking seems to be fine" green
  1181.     fi
  1182. }
  1183.  
  1184. check_table_scans () {
  1185.  
  1186. ## -- Table Scans -- ##
  1187.  
  1188.     cecho "TABLE SCANS" boldblue
  1189.  
  1190.     mysql_status \'Com_select\' com_select
  1191.     mysql_status \'Handler_read_rnd_next\' read_rnd_next
  1192.     mysql_variable \'read_buffer_size\' read_buffer_size
  1193.  
  1194.     if [ -z $read_buffer_size ] ; then
  1195.         mysql_variable \'record_buffer\' read_buffer_size
  1196.     fi
  1197.  
  1198.     human_readable $read_buffer_size read_buffer_sizeHR
  1199.     cecho "Current read_buffer_size = $read_buffer_sizeHR $unit"
  1200.    
  1201.     if [ $com_select -gt 0 ] ; then
  1202.         full_table_scans=$(($read_rnd_next/$com_select))
  1203.         cecho "Current table scan ratio = $full_table_scans : 1"
  1204.         if [ $full_table_scans -ge 4000 ] && [ $read_buffer_size -le 2097152 ] ; then
  1205.             cecho "You have a high ratio of sequential access requests to SELECTs" red
  1206.             cechon "You may benefit from raising " red
  1207.             if [ "$major_version" = '3.23' ] ; then
  1208.                 cechon "record_buffer " red
  1209.             else
  1210.                 cechon "read_buffer_size " red
  1211.             fi
  1212.             cecho "and/or improving your use of indexes." red
  1213.         elif [ $read_buffer_size -gt 8388608 ] ; then
  1214.             cechon "read_buffer_size is over 8 MB " red
  1215.             cecho "there is probably no need for such a large read_buffer" red
  1216.        
  1217.         else
  1218.             cecho "read_buffer_size seems to be fine" green
  1219.         fi
  1220.     else
  1221.         cecho "read_buffer_size seems to be fine" green
  1222.     fi
  1223. }
  1224.  
  1225.  
  1226. check_innodb_status () {
  1227.  
  1228. ## -- InnoDB -- ##
  1229.  
  1230.     mysql_variable \'have_innodb\' have_innodb
  1231.  
  1232.     if [ "$have_innodb" = "YES" ] ; then
  1233.         mysql_variable \'innodb_buffer_pool_size\' innodb_buffer_pool_size
  1234.         mysql_variable \'innodb_additional_mem_pool_size\' innodb_additional_mem_pool_size
  1235.         mysql_variable \'innodb_fast_shutdown\' innodb_fast_shutdown
  1236.         mysql_variable \'innodb_flush_log_at_trx_commit\' innodb_flush_log_at_trx_commit
  1237.         mysql_variable \'innodb_locks_unsafe_for_binlog\' innodb_locks_unsafe_for_binlog
  1238.         mysql_variable \'innodb_log_buffer_size\' innodb_log_buffer_size
  1239.         mysql_variable \'innodb_log_file_size\' innodb_log_file_size
  1240.         mysql_variable \'innodb_log_files_in_group\' innodb_log_files_in_group
  1241.         mysql_variable \'innodb_safe_binlog\' innodb_safe_binlog
  1242.         mysql_variable \'innodb_thread_concurrency\' innodb_thread_concurrency
  1243.  
  1244.         cecho "INNODB STATUS" boldblue
  1245.         innodb_indexes=$($mysql -Bse "/*!50000 SELECT IFNULL(SUM(INDEX_LENGTH),0) from information_schema.TABLES where ENGINE='InnoDB' */")
  1246.         innodb_data=$($mysql -Bse "/*!50000 SELECT IFNULL(SUM(DATA_LENGTH),0) from information_schema.TABLES where ENGINE='InnoDB' */")
  1247.        
  1248.         if [ ! -z "$innodb_indexes" ] ; then
  1249.  
  1250.         mysql_status \'Innodb_buffer_pool_pages_data\' innodb_buffer_pool_pages_data
  1251.         mysql_status \'Innodb_buffer_pool_pages_misc\' innodb_buffer_pool_pages_misc
  1252.         mysql_status \'Innodb_buffer_pool_pages_free\' innodb_buffer_pool_pages_free
  1253.         mysql_status \'Innodb_buffer_pool_pages_total\' innodb_buffer_pool_pages_total
  1254.  
  1255.         mysql_status \'Innodb_buffer_pool_read_ahead_seq\' innodb_buffer_pool_read_ahead_seq
  1256.         mysql_status \'Innodb_buffer_pool_read_requests\' innodb_buffer_pool_read_requests
  1257.  
  1258.         mysql_status \'Innodb_os_log_pending_fsyncs\' innodb_os_log_pending_fsyncs
  1259.         mysql_status \'Innodb_os_log_pending_writes\'   innodb_os_log_pending_writes
  1260.         mysql_status \'Innodb_log_waits\' innodb_log_waits
  1261.  
  1262.         mysql_status \'Innodb_row_lock_time\' innodb_row_lock_time
  1263.         mysql_status \'Innodb_row_lock_waits\' innodb_row_lock_waits
  1264.  
  1265.         human_readable $innodb_indexes innodb_indexesHR
  1266.         cecho "Current InnoDB index space = $innodb_indexesHR $unit"
  1267.         human_readable $innodb_data innodb_dataHR
  1268.         cecho "Current InnoDB data space = $innodb_dataHR $unit"
  1269.         percent_innodb_buffer_pool_free=$(($innodb_buffer_pool_pages_free*100/$innodb_buffer_pool_pages_total))
  1270.         cecho "Current InnoDB buffer pool free = "$percent_innodb_buffer_pool_free" %"
  1271.  
  1272.         else
  1273.         cecho "Cannot parse InnoDB stats prior to 5.0.x" red
  1274.         $mysql -s -e "SHOW /*!50000 ENGINE */ INNODB STATUS\G"
  1275.         fi
  1276.  
  1277.         human_readable $innodb_buffer_pool_size innodb_buffer_pool_sizeHR
  1278.         cecho "Current innodb_buffer_pool_size = $innodb_buffer_pool_sizeHR $unit"
  1279.         cecho "Depending on how much space your innodb indexes take up it may be safe"  
  1280.         cecho "to increase this value to up to 2 / 3 of total system memory"
  1281.     else
  1282.         cecho "No InnoDB Support Enabled!" boldred
  1283.     fi
  1284. }
  1285.  
  1286. total_memory_used () {
  1287.  
  1288. ## -- Total Memory Usage -- ##
  1289.     cecho "MEMORY USAGE" boldblue
  1290.  
  1291.     mysql_variable \'read_buffer_size\' read_buffer_size
  1292.     mysql_variable \'read_rnd_buffer_size\' read_rnd_buffer_size
  1293.     mysql_variable \'sort_buffer_size\' sort_buffer_size
  1294.     mysql_variable \'thread_stack\' thread_stack
  1295.     mysql_variable \'max_connections\' max_connections
  1296.     mysql_variable \'join_buffer_size\' join_buffer_size
  1297.     mysql_variable \'tmp_table_size\' tmp_table_size
  1298.     mysql_variable \'max_heap_table_size\' max_heap_table_size
  1299.     mysql_variable \'log_bin\' log_bin
  1300.     mysql_status \'Max_used_connections\' max_used_connections
  1301.  
  1302.     if [ "$major_version" = "3.23" ] ; then
  1303.         mysql_variable \'record_buffer\' read_buffer_size
  1304.         mysql_variable \'record_rnd_buffer\' read_rnd_buffer_size
  1305.         mysql_variable \'sort_buffer\' sort_buffer_size
  1306.     fi
  1307.  
  1308.     if [ "$log_bin" = "ON" ] ; then
  1309.         mysql_variable \'binlog_cache_size\' binlog_cache_size
  1310.     else
  1311.         binlog_cache_size=0
  1312.     fi
  1313.  
  1314.     if [ $max_heap_table_size -le $tmp_table_size ] ; then
  1315.         effective_tmp_table_size=$max_heap_table_size
  1316.     else
  1317.         effective_tmp_table_size=$tmp_table_size
  1318.     fi
  1319.  
  1320.  
  1321.     per_thread_buffers=$(echo "($read_buffer_size+$read_rnd_buffer_size+$sort_buffer_size+$thread_stack+$join_buffer_size+$binlog_cache_size)*$max_connections" | bc -l)
  1322.     per_thread_max_buffers=$(echo "($read_buffer_size+$read_rnd_buffer_size+$sort_buffer_size+$thread_stack+$join_buffer_size+$binlog_cache_size)*$max_used_connections" | bc -l)
  1323.  
  1324.         mysql_variable \'innodb_buffer_pool_size\' innodb_buffer_pool_size
  1325.         if [ -z $innodb_buffer_pool_size ] ; then
  1326.         innodb_buffer_pool_size=0
  1327.         fi
  1328.  
  1329.         mysql_variable \'innodb_additional_mem_pool_size\' innodb_additional_mem_pool_size
  1330.         if [ -z $innodb_additional_mem_pool_size ] ; then
  1331.         innodb_additional_mem_pool_size=0
  1332.         fi
  1333.  
  1334.         mysql_variable \'innodb_log_buffer_size\' innodb_log_buffer_size
  1335.         if [ -z $innodb_log_buffer_size ] ; then
  1336.         innodb_log_buffer_size=0
  1337.         fi
  1338.  
  1339.         mysql_variable \'key_buffer_size\' key_buffer_size
  1340.  
  1341.         mysql_variable \'query_cache_size\' query_cache_size
  1342.         if [ -z $query_cache_size ] ; then
  1343.         query_cache_size=0
  1344.         fi
  1345.  
  1346.     global_buffers=$(echo "$innodb_buffer_pool_size+$innodb_additional_mem_pool_size+$innodb_log_buffer_size+$key_buffer_size+$query_cache_size" | bc -l)
  1347.  
  1348.  
  1349.     max_memory=$(echo "$global_buffers+$per_thread_max_buffers" | bc -l)
  1350.     total_memory=$(echo "$global_buffers+$per_thread_buffers" | bc -l)
  1351.  
  1352.     pct_of_sys_mem=$(echo "scale=0; $total_memory*100/$physical_memory" | bc -l)
  1353.  
  1354.     if [ $pct_of_sys_mem -gt 90 ] ; then
  1355.         txt_color=boldred
  1356.         error=1
  1357.     else
  1358.         txt_color=
  1359.         error=0
  1360.     fi 
  1361.  
  1362.     human_readable $max_memory max_memoryHR
  1363.     cecho "Max Memory Ever Allocated : $max_memoryHR $unit" $txt_color
  1364.     human_readable $per_thread_buffers per_thread_buffersHR
  1365.     cecho "Configured Max Per-thread Buffers : $per_thread_buffersHR $unit" $txt_color
  1366.     human_readable $global_buffers global_buffersHR
  1367.     cecho "Configured Max Global Buffers : $global_buffersHR $unit" $txt_color
  1368.     human_readable $total_memory total_memoryHR
  1369.     cecho "Configured Max Memory Limit : $total_memoryHR $unit" $txt_color
  1370. #   human_readable $effective_tmp_table_size effective_tmp_table_sizeHR
  1371. #   cecho "Plus $effective_tmp_table_sizeHR $unit per temporary table created"
  1372.     human_readable $physical_memory physical_memoryHR
  1373.     cecho "Physical Memory : $physical_memoryHR $unit" $txt_color
  1374.     if [ $error -eq 1 ] ; then
  1375.         printf "\n"
  1376.         cecho "nMax memory limit exceeds 90% of physical memory" $txt_color
  1377.     else
  1378.         cecho "Max memory limit seem to be within acceptable norms" green
  1379.     fi
  1380.     unset txt_color
  1381. }
  1382.  
  1383. ## Required Functions  ##
  1384.  
  1385. login_validation () {
  1386.     check_for_socket        # determine the socket location -- 1st login
  1387.     check_for_plesk_passwords   # determine the login method -- 2nd login
  1388.     check_mysql_login       # determine if mysql is accepting login -- 3rd login
  1389.     export major_version=$($mysql -Bse "SELECT SUBSTRING_INDEX(VERSION(), '.', +2)")
  1390.     export mysql_version_num=$($mysql -Bse "SELECT LEFT(REPLACE(SUBSTRING_INDEX(VERSION(), '-', +1), '.', ''),4)" )
  1391. }
  1392.  
  1393. shared_info () {
  1394.     export major_version=$($mysql -Bse "SELECT SUBSTRING_INDEX(VERSION(), '.', +2)")
  1395.     export mysql_version_num=$($mysql -Bse "SELECT LEFT(REPLACE(SUBSTRING_INDEX(VERSION(), '-', +1), '.', ''),4)" )
  1396.     mysql_status \'Questions\' questions
  1397. #   socket_owner=$(find -L $socket -printf '%u\n')
  1398.     socket_owner=$(ls -nH $socket | awk '{ print $3 }')
  1399. }
  1400.    
  1401.  
  1402. get_system_info () {
  1403.  
  1404.     export OS=$(uname)
  1405.    
  1406.     # Get information for various UNIXes
  1407.     if [ "$OS" = 'Darwin' ]; then
  1408.     ps_socket=$(netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }' | head -1)
  1409.     found_socks=$(netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }')
  1410.         export physical_memory=$(sysctl -n hw.memsize)
  1411.     export duflags=''
  1412.     elif [ "$OS" = 'FreeBSD' ] || [ "$OS" = 'OpenBSD' ]; then
  1413.     ## On FreeBSD must be root to locate sockets.
  1414.     ps_socket=$(netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }' | head -1)
  1415.     found_socks=$(netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }')
  1416.         export physical_memory=$(sysctl -n hw.realmem)
  1417.     export duflags=''
  1418.     elif [ "$OS" = 'Linux' ] ; then
  1419.     ## Includes SWAP
  1420.         ## export physical_memory=$(free -b | grep -v buffers |  awk '{ s += $2 } END { printf("%.0f\n", s ) }')
  1421.     ps_socket=$(netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }' | head -1)
  1422.     found_socks=$(netstat -ln | awk '/mysql(d)?\.sock/ { print $9 }')
  1423.     export physical_memory=$(awk '/^MemTotal/ { printf("%.0f", $2*1024 ) }' < /proc/meminfo)
  1424.     export duflags='-b'
  1425.     elif [ "$OS" = 'SunOS' ] ; then
  1426.     ps_socket=$(netstat -a | awk '/mysql(d)?.sock/ { print $5 }' | head -1)
  1427.     found_socks=$(netstat -a | awk '/mysql(d)?.sock/ { print $5 }')
  1428.     export physical_memory=$(prtconf | awk '/^Memory\ size:/ { print $3*1048576 }')
  1429.     fi
  1430. }
  1431.  
  1432.  
  1433. ## Optional Components Groups ##
  1434.  
  1435. banner_info () {
  1436.     shared_info
  1437.     print_banner        ; echo
  1438.     check_mysql_version ; echo
  1439.     post_uptime_warning ; echo
  1440. }
  1441.  
  1442. misc () {
  1443.     shared_info
  1444.     check_slow_queries  ; echo
  1445.     check_binary_log    ; echo
  1446.     check_threads       ; echo
  1447.     check_used_connections  ; echo
  1448.     check_innodb_status ; echo
  1449. }
  1450.  
  1451. memory () {
  1452.     shared_info
  1453.     total_memory_used   ; echo
  1454.     check_key_buffer_size   ; echo
  1455.     check_query_cache   ; echo
  1456.     check_sort_operations   ; echo
  1457.     check_join_operations   ; echo
  1458. }
  1459.  
  1460. file () {
  1461.     shared_info
  1462.     check_open_files    ; echo
  1463.     check_table_cache   ; echo
  1464.     check_tmp_tables    ; echo
  1465.     check_table_scans   ; echo
  1466.     check_table_locking ; echo
  1467. }
  1468.  
  1469. all () {
  1470.     banner_info
  1471.     misc
  1472.     memory
  1473.     file
  1474. }
  1475.  
  1476. prompt () {
  1477.     prompted='true'
  1478.     read -p "Username [anonymous] : " user
  1479.     read -rp "Password [<none>] : " pass
  1480.     cecho " "
  1481.     read -p "Socket [ /var/lib/mysql/mysql.sock ] : " socket
  1482.     if [ -z $socket ] ; then
  1483.         export socket='/var/lib/mysql/mysql.sock'
  1484.     fi
  1485.  
  1486.     if [ -z $pass ] ; then
  1487.     export mysql="mysql -S $socket -u$user"
  1488.     export mysqladmin="mysqladmin -S $socket -u$user"
  1489.     else
  1490.         export mysql="mysql -S $socket -u$user -p$pass"
  1491.         export mysqladmin="mysqladmin -S $socket -u$user -p$pass"
  1492.     fi
  1493.  
  1494.     check_for_socket
  1495.     check_mysql_login
  1496.  
  1497.     if [ $? = 1 ] ; then
  1498.         exit 1
  1499.     fi
  1500.     read -p "Mode to test - banner, file, misc, mem, innodb, [all] : " REPLY
  1501.     if [ -z $REPLY ] ; then
  1502.         REPLY='all'
  1503.     fi
  1504.     case $REPLY in
  1505.             banner | BANNER | header | HEADER | head | HEAD)
  1506.         banner_info
  1507.         ;;
  1508.         misc | MISC | miscelaneous )
  1509.         misc
  1510.         ;;
  1511.             mem | memory |  MEM | MEMORY )
  1512.         memory
  1513.         ;;
  1514.         file | FILE | disk | DISK )
  1515.         file
  1516.         ;;
  1517.         innodb | INNODB )
  1518.         innodb
  1519.         ;;
  1520.         all | ALL )
  1521.         cecho " "
  1522.         all
  1523.         ;;
  1524.         * )
  1525.         cecho "Invalid Mode!  Valid options are 'banner', 'misc', 'memory', 'file', 'innodb' or 'all'" boldred
  1526.         exit 1
  1527.         ;;
  1528.     esac
  1529. }
  1530.  
  1531. ## Address environmental differences ##
  1532. get_system_info
  1533. # echo $ps_socket
  1534.  
  1535. if [ -z "$1" ] ; then
  1536.     login_validation
  1537.     mode='ALL'
  1538. elif [ "$1" = "prompt" ] || [ "$1" = "PROMPT" ] ; then
  1539.     mode=$1
  1540. elif [ "$1" != "prompt" ] || [ "$1" != "PROMPT" ] ; then
  1541.     login_validation
  1542.     mode=$1
  1543. fi
  1544.  
  1545. case $mode in
  1546.     all | ALL )
  1547.     cecho " "
  1548.     all
  1549.     ;;
  1550.     mem | memory |  MEM | MEMORY )
  1551.     cecho " "
  1552.     memory
  1553.     ;;
  1554.     file | FILE | disk | DISK )
  1555.     cecho " "
  1556.     file
  1557.     ;;
  1558.     banner | BANNER | header | HEADER | head | HEAD )
  1559.     banner_info
  1560.     ;;
  1561.     misc | MISC | miscelaneous )
  1562.     cecho " "
  1563.     misc
  1564.     ;;
  1565.     innodb | INNODB )
  1566.     banner_info
  1567.     check_innodb_status ; echo
  1568.     ;;
  1569.     prompt | PROMPT )
  1570.     prompt
  1571.     ;;
  1572.     *)
  1573.     cecho "usage: $0 [ all | banner | file | innodb | memory | misc | prompt ]" boldred
  1574.     exit 1  
  1575.     ;;
  1576. esac
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement