MySQL
Contents
- 1 Table size by type
- 2 how to convert a table with MySQL
- 3 how to convert all tables in a database
- 4 Checking max connections and if it was hit
- 5 Explaining mysqladmin command output
- 6 Setting my.cnf
- 7 MySQL ops and highest historic number of connections since MySQL was last started
- 8 recreating a DB
- 9 Dumping
- 10 Playing with tables and other fun stuffs
- 11 Fragmented Tables
- 12 MySql
- 13 Correct way to upgrade mysql in cpanel box
- 14 Innodb Corruption Repair
- 15 Overview
- 16 Giving someone permissions to do stuff
- 17 MySQL 4
- 18 Exporting and Importing
- 19 MySQL Variables
- 19.1 auto_increment_*
- 19.2 concurrent_insert
- 19.3 datadir
- 19.4 delayed_insert*
- 19.5 hostname
- 19.6 innodb_file_per_table
- 19.7 interactive_timeout
- 19.8 join_buffer_size
- 19.9 key_buffer_size
- 19.10 low_priority_updates
- 19.11 lower_case_table_names
- 19.12 max_allowed_packet
- 19.13 max_connections
- 19.14 pid_file
- 19.15 port
- 19.16 query_cache_size
- 19.17 query_cache_wlock_invalidate
- 19.18 sort_buffer_size
- 19.19 read_only
- 19.20 table_lock_wait_timeout
- 19.21 time_zone
- 19.22 tmpdir
- 19.23 version
- 19.24 wait_timeout
- 20 Show Status
- 21 mysqltuner
- 22 GRANT TRIGGER PERMISSION
Table size by type
SELECT engine, count(*) tables, concat(round(sum(table_rows)/1000000,2),'M') rows, concat(round(sum(data_length)/(1024*1024*1024),2),'G') data, concat(round(sum(index_length)/(1024*1024*1024),2),'G') idx, concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G') total_size, round(sum(index_length)/sum(data_length),2) idxfrac FROM information_schema.TABLES GROUP BY engine ORDER BY sum(data_length+index_length) DESC LIMIT 10; +------------+--------+---------+---------+--------+------------+---
how to convert a table with MySQL
USE dbname ALTER TABLE wp_comments ENGINE=InnoDB;
how to convert all tables in a database
for i in `mysql -BN -e "SELECT concat(TABLE_SCHEMA, '.', TABLE_NAME) FROM information_schema.tables WHERE engine = 'MyISAM' AND table_schema = 'dbname'"`; do echo $i; mysql -e "ALTER TABLE $i ENGINE=InnoDB;"; done
Checking max connections and if it was hit
mysql -e "show variables like '%max_connections%';"
mysql -e "show global status like '%max_u%';"
Explaining mysqladmin command output
| 4268 | TESTDB_USER | localhost | TESTDB_DB1 | Query | 361 | Sending data | SELECT COUNT(*) AS numrows FROM (tblarchivedomain) WHERE title LIKE '%google.com%' OR `doma |
If you're not familiar with the output from the mysqladmin command, this starts by displaying the MySQL process ID, followed by the MySQL user (TESTDB_USER), the server the connection is from (localhost), the database the connection is to (TESTDB_DB1), the command being run (Query), the time that is has currently been running for in seconds (361), the state of that command (sending data) and the information of that command which in this case is part of the query data.
Setting my.cnf
## Good starting points are 64M, then double this value as RAM doubles. 1GB RAM = 64M, 2GB = 128M, 4GB = 256M. Should not be set higher than 4GB( can be removed from the deployed version of the file, just added this comment to explain how this should scale) key_buffer = 256M ## Good starting points are 64M, then double this value as RAM doubles. 1GB RAM = 64M, 2GB = 128M, 4GB = 256M, etc, etc (can be removed from the deployed version of the file, just added this comment to explain how this should scale) innodb_buffer_pool_size = 512M ## Misc settings that can be changed if you have a reason to change them, otherwise these should be good starting points ## max_allowed_packet = 16M table_open_cache = 1024 innodb_additional_mem_pool_size = 8M ## If ACID compliant transactions are not required, this can be changed to either 0 or 2 for better performance at the risk of transaction loss. #innodb_flush_log_at_trx_commit = 1 innodb_log_buffer_size = 8M innodb_file_per_table ## Changing this setting requires you to stop MySQL, move the current logs out of the way, and then starting MySQL ## innodb_log_file_size = 128M ## Diagnostics ## #slow_query_log = 1 #slow_query_log_file = /var/lib/mysql/slowquery.log #long_query_time = 1 ## Maintenance and Recovery Settings ## default-storage-engine=MyISAM
MySQL ops and highest historic number of connections since MySQL was last started
mysqlops() { echo -e "$Green\n=== MySQL Configuration ===$NoColor\n" echo "MySQL Version: `mysql -V | awk '{print $5}' | cut -d',' -f1`" mysqladmin extended-status | grep Max_used_connections | awk '{print $2,$4}' sed -n '/\[mysqld\]/,/\[/p' $MYSQL|grep -v "\["|grep "[a-zA-Z0-9]" echo "I/O Wait: `echo ${IOSTAT[1]}`"
http://wiki.mikejung.biz/index.php?title=MySQL
recreating a DB
Destroy and re-create the new database
mysql -e "DROP DATABASE theDATA_new;" mysql -e "CREATE DATABASE theDATA_new;"
Dump and import data from the old to the new
mysqldump theDATA_work > /backup/theDATA_work.sql mysql theDATA_new < /backup/theDATA_work.lwbak.sql
Get the checksums from both of the databases:
for i in $( mysql -e 'use theDATA_work; show tables\G' |grep -v ^'*'|cut -d: -f2 ); do
echo "$i" mysql -e "CHECKSUM TABLE theDATA_work.$i;" | tail -n1 | awk '{print $2}' echo
done > /root/db_checksums_1.txt
for i in $( mysql -e 'use theDATA_new; show tables\G' |grep -v ^'*'|cut -d: -f2 ); do
echo "$i" mysql -e "CHECKSUM TABLE theDATA_new.$i;" | tail -n1 | awk '{print $2}' echo
done > /root/db_checksums_2.txt
And then diff the files:
diff /root/db_checksums_1.txt /root/db_checksums_2.txt
Dumping
To dump all mysql DB's into their own file
for i in `mysql -e "show databases;"`; do mysqldump $i > /home/mysqlbackups/$i.sql; done
or in one file
mysqldump --all-databases > all_databases.sql
or in the backup dir
mkdir -p /backup/mysqldumps cd /backup/mysqldumps for i in $(mysql -e "show databases;" | grep -v Database); do echo dumping $i; `mysqldump $i > $i.sql`; done
Playing with tables and other fun stuffs
lists the databases
simply mysql then
show databases;
to load a database
be in the directory of the sql file make sure it is not compressed gunzip if needed
mysql DBNAME < DBFILE
Fragmented Tables
wget -O /scripts/fragmented.sh http://layer3.liquidweb.com/scripts/jhayhoe/fragmented.sh chmod +x /scripts/fragmented.sh /scripts/fragmented.sh
Optimization Scripts
While the default configs here are a good starting point. These scripts will help in finding any issues with the users current MySQL config.
Note: I like to run these like : '/scripts/tuning-primer.sh > /root/tuning-primer.txt[n]' This saves the output, so you don't feel compelled to add it as a note to a ticket or admin comments. You can also use it to compare the results after 48 hours. This is a great way to document these changes.
You can run this from my server:
exec 3<&1 && bash <&3 <(curl -sq https://jparks.work/tuning-primer.sh)
or it is offered externally:
wget -O /scripts/tuning-primer.sh http://day32.com/MySQL/tuning-primer.sh chmod 700 /scripts/tuning-primer.sh /scripts/tuning-primer.sh
Another version here:
wget -O /scripts/mysqltuner.pl https://raw.github.com/major/MySQLTuner-perl/master/mysqltuner.pl chmod 700 /scripts/mysqltuner.pl /scripts/mysqltuner.pl
Optimizing a MySQL database server is beyond this tutorial but for the majority of our customers these will do the job.
Edit /etc/my.cnf and enter the recommended settings.
Here's a nice little optimize script that reorganizes all the indexes for all tables on the machine. Good for when mysql indexes are fragmented. Fragmentation like this can cause load on the server and this script is pretty helpful a majority of the time.
This script can crash forums. Use judiciously, and remember to schedule it to run during off-peak hours.}} for i in $(mysql -e "show databases;" | sed 's/Database//') ; do for each in $(mysql -e "use $i; show tables;" \ | sed 's/Tables.*//' ;) ; do mysql -e "use $i ; optimize table $each" ; done ; done
Not every table is fragmented and needs optimization. Similar to how mysqltuner.pl checks for fragmented tables, the following command recognizes all databases and checks for only fragmented tables.
for i in `mysql -e "show databases;"|sed 's/Database//'`; do for each in `mysql -e "show table status where Data_free > 0;" $i|tail -n +2|grep -v InnoDB|awk '{print $1}'`; do mysqlcheck -o $i $each; done ; done
Older MySQL versions cannot run the command "show table status where Data_free > 0;". This one-liner is modified for older MySQL versions.
for i in `mysql -e "show databases;"|sed 's/Database//'`; do for each in `mysql -e "show table status;" $i|tail -n +2|awk '{print $1,$10}'|grep -v " 0"|grep -v InnoDB|awk '{print $1}'`; do mysqlcheck -o $i $each; done ; done
Alternatively you can do this (and rebuild join order hints) from mysqlcheck:
mysqlcheck -Asa && mysqlcheck -Aso
A few custom configurations
query_cache_size=64M # 32MB for every 1GB of RAM unless it is VPS and then use no more than 8MB for each 512M of RAM (4M is probably best for most sites) key_buffer=64M # 64MB for every 1GB of RAM sort_buffer_size=1M # 1MB for every 1GB of RAM read_buffer_size=1M # 1MB for every 1GB of RAM read_rnd_buffer_size=1M # 1MB for every 1GB of RAM
MySQL 5.5.xx will not start if you add either of the following two options into my.cnf safe-show-database skip-locking
The following configurations are only meant as a starting point. These often need tweaking (sometimes large amounts of it) depending on the customers needs. Use common sense and the tuning primer to aid you in optimizing mysql.
MAKE A BACKUP OF THE OLD CONFIGURATION FILE BEFORE CHANGING ANYTHING!!! Do NOT simply copy and paste these in as you could seriously break folks innoDB if it is present. Please use these as a guideline only and not an end all to optimization}}
For Legacy VPS, Vservers, and very old hardware
For Servers with MySQL 5.1 and higher, the following changes will need to be made:
Remove 'safe-show-database' Change 'skip-locking' -> 'skip-external-locking'
[mysqld] max_connections = 50 safe-show-database skip-locking key_buffer = 16M open_files_limit = 8190 table_cache = 3184 thread_cache = 2 sort_buffer_size = 512K net_buffer_length = 8K read_buffer_size = 256K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M query_cache_size = 8M max_heap_table_size = 32M tmp_table_size = 32M wait_timeout = 30 interactive_timeout = 150 [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash [isamchk] key_buffer = 16M sort_buffer_size = 10M read_buffer = 2M write_buffer = 2M [myisamchk] key_buffer = 16M sort_buffer_size = 10M read_buffer = 2M write_buffer = 2M
For Dedicated and Storm Servers
1-2G RAM
For Servers with MySQL 5.1 and higher, the following changes will need to be made:
Remove 'safe-show-database' Change 'skip-locking' -> 'skip-external-locking'
[mysqld] max_connections = 50 safe-show-database skip-locking key_buffer = 128M open_files_limit = 8190 table_cache = 3184 sort_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 2M myisam_sort_buffer_size = 64M query_cache_size = 32M max_heap_table_size = 48M tmp_table_size = 48M thread_cache_size = 8 wait_timeout = 30 interactive_timeout = 300 [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash [isamchk] key_buffer = 96M sort_buffer_size = 64M read_buffer = 2M write_buffer = 2M [myisamchk] key_buffer = 96M sort_buffer_size = 64M read_buffer = 2M write_buffer = 2M
3-8G RAM
For Servers with MySQL 5.1 and higher, the following changes will need to be made:
Remove 'safe-show-database' Change 'skip-locking' -> 'skip-external-locking'
[mysqld] max_connections = 64 safe-show-database skip-locking key_buffer = 192M open_files_limit = 8190 table_cache = 3184 sort_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 2M myisam_sort_buffer_size = 64M query_cache_size = 96M max_heap_table_size = 64M tmp_table_size = 64M thread_cache_size = 16 wait_timeout = 45 interactive_timeout = 600 [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash [isamchk] key_buffer = 128M sort_buffer_size = 64M read_buffer = 2M write_buffer = 2M [myisamchk] key_buffer = 128M sort_buffer_size = 64M read_buffer = 2M write_buffer = 2M
More than 8G RAM
For Servers with MySQL 5.1 and higher, the following changes will need to be made:
Remove 'safe-show-database' Change 'skip-locking' -> 'skip-external-locking'
[mysqld] max_connections = 128 safe-show-database skip-locking key_buffer = 384M open_files_limit = 8190 table_cache = 3184 sort_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 8M myisam_sort_buffer_size = 64M query_cache_size = 128M max_heap_table_size = 64M tmp_table_size = 64M thread_cache_size = 32 wait_timeout = 120 connect_timeout = 10 interactive_timeout = 1200 [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash [isamchk] key_buffer = 256M sort_buffer_size = 128M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout
MySql
to find mysql version type mysql then:
SHOW VARIABLES LIKE "%version%";
A row and a record are the same thing in MySQL SQL statements end with a semi-colon
MYSQL daemon /usr/sbin/mysqld
mySQL data directory is in /var/lib/mySQL
mySQL error log /var/lib/mysql/hostname.err
MySqlAdmin status shows whats going on on the server
mysqldump - exports database info
mysqldump db_name > db_name.sql (exports to a file) mysqldump db_name table_name > db_name-Table_name.sql (exports specified table to a file) mysqldump db_name1, db_name2 > db_names.sql (exports 2 databases to a file)
to reload from a dumped database switch the arrow
mysqldump dbname < db_name.sql
myisam tables are simple and good for begginners and they use alot less memory
do not delete the log file for inodb it can be used to rebuild the DB
check out the scripts for tuning in the LW wiki do not run the script immediatly after starting mySQL wait at least 48 hrs so that peak usage can hit so it can give an accurate reading.
Mysqlcheck -aor --all-databases (defrags and repairs databases) requires alot of space in var oor tmp and could crash the server so make sure their is room
BEFORE DOING A MYSQL REPAIR DO A DU
myisamchk cannot be ran while the server is running!
MySQL databases are found in /var/lib/mysql/cpanel_accountname sometimes and may have 3 different file extensions for each database.
save your work by preforming a mysql dump this requires including the cpanel name sometimes (wordpress)
cust would like help importing a DB for his wordpress site would like wp_calendar imported into wp_my_calendar vspac is the name of the cpanel account and folder
backup both files
mysqldump vspac_main wp_calendar > wp_calendar.sql.bak mysqldump vspac_main wp_my_calendar > wp_my_calendar.sql.bak
mysqldump vspac_main wp_my_calendar < wp_calendar.sql.bak
service mysql restart
Correct way to upgrade mysql in cpanel box
Firstly Check the versions currently installed (after the upgrade easy apache wont report the php version so we do this first.)
php -v mysqladmin version
Back up the databases before anything else.
mkdir /home/sqlbackup for db in `mysql -s -B -e "show databases"`;do mysqldump $db > /home/sqlbackup/$db.sql.`date +%Y%m%d%I`;done
Change mysql-version to the version you want.
vim /var/cpanel/cpanel.config
change mysql-version to what you want (IE...5.1, 5.5))
To do 5.1 to 5.5 sed -i -e 's#mysql-version=5.1#mysql-version=5.5#g' /var/cpanel/cpanel.config To do 5.5 to 5.6 sed -i -e 's#mysql-version=5.5#mysql-version=5.6#g' /var/cpanel/cpanel.config
READ THE DAMN THING, make sure there arent errors on the screen
/usr/local/cpanel/whostmgr/bin/whostmgr2 --updatetweaksettings
READ THE DAMN THING, make sure there arent errors on the screen
/scripts/mysqlup --force mysqladmin version
Make sure the EA options all match current versions.
/scripts/easyapache Grats if you got here with no errors
Innodb Corruption Repair
https://forums.cpanel.net/threads/innodb-corruption-repair-guide.418722/
INNODB DATABASE REPAIR
set recovery to 4. dumping DBs.
root@server:[/backup/mysql-restore/dumps]: for DB in $(mysql -Bse "show databases;"|grep -E -v "performance_schema|information_schema"); do echo "dumping ${DB}"; mysqldump --single-transaction $DB > $DB.sql; done
shutdown mysql and re-syncd the datadir
root@server:[~]: rsync -atv /var/lib/mysql/ /backup/mysql-restore/mysql/ --exclude=centos6.template.liquidweb.com.err
moved and recreated datadir
root@server:[~]: mv /var/lib/mysql{,.old} root@server:[~]: mkdir /var/lib/mysql root@server:[~]: chown mysql. /var/lib/mysql root@server:[~]: chmod 751 /var/lib/mysql root@server:[~]: mysql_install_db --datadir=/var/lib/mysql --user=mysql
disabled innodb recovery and started mysql
root@server:[~]: vim /etc/my.cnf root@server:[~]: /etc/init.d/mysql start Starting MariaDB.180911 20:33:45 mysqld_safe Logging to '/var/lib/mysql/centos6.template.liquidweb.com.err'.
180911 20:33:45 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
i also had to comment out several things from my.cnf in order to get a stable mysql running after fresh install
#local-infile=0 #max_connections=80 #thread_cache_size=128 #key_buffer=64M #max_connect_errors=20 #thread_concurrency=4 #concurrent_insert=2 #local-infile=0 #default-storage-engine=MyISAM
restoring mysql db
root@server:[~]: rsync -atv --exclude=*.ibd /backup/mysql-restore/mysql/mysql/ /var/lib/mysql/mysql/
root@server:[~]: /etc/init.d/mysql start
Starting MariaDB.180911 20:44:39 mysqld_safe Logging to '/var/lib/mysql/centos6.template.liquidweb.com.err'. 180911 20:44:39 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
restoring dbs
root@server:[/backup/mysql-restore/dumps]: mv mysql.sql ../ root@server:[/backup/mysql-restore/dumps]: for DB in $(\ls|cut -d. -f1); do echo "creating ${DB}"; mysqladmin create $DB; mysql $DB < $DB.sql; done
those completed, and everything looks good at this point
root@server:[/backup/mysql-restore/dumps]: mysqlcheck -Aas
uncommented innodb_file_per_table
Overview
So, with MySQL, permissions on databases/tables is much like permissions on files in Unix/LInux land. You need permission to add new rows to a table before you can add those rows, and for even finer control, you need permission at a particular IP.
To add to the fun, the way users and grants are set up got changed in MySQL 5.0.x. This means that some things aren't there, like the mysql.users table.
In this wiki, we're first going to cover MySQL grants for MySQL 5, and then we'll go over the differences in MySQL 4.x
If you're on a cPanel box
If you're on a cPanel box, do ALL of this through cPanel. On cPanel boxes, don't create databases or users directly. Doing this directly through MySQL on a cPanel box breaks cPanel database mapping, and the databases/users won't be backed up. Don't do it.
If you DO decide to not heed this warning, you can correct the mapping by running this command:
/usr/local/cpanel/bin/setupdbmap
Giving someone permissions to do stuff
Assuming you're on MySQL 5.0+
To create a new user
<source lang="mysql"> CREATE USER 'jack'@'localhost' IDENTIFIED BY 'mypass'; </source>
OR
<source lang="mysql"> CREATE USER 'jack'@'%' IDENTIFIED BY 'mypass'; </source>
OR
<source lang="mysql"> CREATE USER 'jack'@'69.16.222.127' IDENTIFIED BY 'mypass'; </source>
A note on unique users
Let's look at creating a user, at a specific IP, with a specific password. It's important to keep in mind, you can have a username at localhost, you can have the same username at 69.16.222.%, you can have the same username at 69.16.222.127, and the same username at %. (% is the wildcard by the way). However, if you have all four of these, that's 4 users. The username is paired to the IP, and you have four seperate password fields in this case.
To demonstrate this, let's look at a query:
<source lang="mysql"> mysql> SELECT user, host, password FROM mysql.user; +---------------+------------------------------------+-------------------------------------------+ | user | host | password | +---------------+------------------------------------+-------------------------------------------+ | root | localhost | *B145E398D3DCFFFE82B2DC502E28AAC590EC07FF | | root | 101.dc2-vps-template.liquidweb.com | *B145E398D3DCFFFE82B2DC502E28AAC590EC07FF | | root | 127.0.0.1 | *B145E398D3DCFFFE82B2DC502E28AAC590EC07FF | | leechprotect | localhost | *E8057E90AB8D4E51239A06C87FF1007ECEEB5414 | | eximstats | localhost | *4C78EFC745475E0748EC4EBA1EB9901D83C4C880 | | cphulkd | localhost | *11FB5E15B6989F4F33181104BB303B7E4C226DE3 | | cpldap | localhost | *61697BCBA52977DFF38254BF1723AF2240039A65 | | roundcube | localhost | *945077E9B53337701826CC615E128D3BD3102495 | | horde | localhost | *15FB21CA888B3182E17B01102EC6CBE7B45BCE81 | | modsec | localhost | *65E12BD8940E523B6C35780D0B255C1E300475B0 | | jhayhurs | localhost | *B2EE6F1F6C7712CF4D2B38EC8A4BE9759E2EF63F | | jhayhurs | 192.168.1.% | *B2EE6F1F6C7712CF4D2B38EC8A4BE9759E2EF63F | | imscared | localhost | 06e0a7e85fb72a63 | | mail | localhost | 29fc7d4049d4cdfb | | jhayhurs_rage | localhost | *E0A58E1FFFD420C25B63DE31B705C995304B12C1 | | jhayhurs_rage | 192.168.1.% | *E0A58E1FFFD420C25B63DE31B705C995304B12C1 | +---------------+------------------------------------+-------------------------------------------+ 16 rows in set (0.00 sec)
mysql> </source>
Giving a user permissions to a database
Remember in MySQL 5.x and later, everything will revolve around users. Users are an object in the database which is granted permission to administer the RDBMS, or administer individual databases, or perform particular functions on databases. This means that the authentication realm for that user is consistent across the entire RDBMS, and when you update their password, you only have to do this in one place.
To give a user all privileges to all tables in a database (lwtest), simply use the following statement:
<source lang="mysql"> mysql> GRANT ALL
-> ON lwtest.* -> TO 'somebody'@'localhost';
</source>
What if you only want some privileges?
<source lang="mysql"> mysql> GRANT SELECT,INSERT,UPDATE,DELETE
-> ON lwtest.* -> TO 'somebody'@'localhost';
</source>
What if you only want one table?
<source lang="mysql"> mysql> GRANT SELECT,INSERT,UPDATE,DELETE
-> ON lwtest.sometable -> TO 'somebody'@'localhost';
</source>
It's similar adding permissions to other stuff.
Showing permissions on a database
Remember, now, you need permissions to do whatever you want to do on the table. You can use:
<source lang="mysql"> mysql> show grants; +----------------------------------------------------------------------------------------------------------------------------------------+ | Grants for root@localhost | +----------------------------------------------------------------------------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*B145E398D3DCFFFE82B2DC502E28AAC590EC07FF' WITH GRANT OPTION | +----------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) </source>
Or you can specify a user or location:
<source lang="mysql"> mysql> show grants for root@localhost; +----------------------------------------------------------------------------------------------------------------------------------------+ | Grants for root@localhost | +----------------------------------------------------------------------------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*B145E398D3DCFFFE82B2DC502E28AAC590EC07FF' WITH GRANT OPTION | +----------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) </source>
If you want to see the grants for a specific user for all locations, you can leave off the @host portion, and it will do a wildcard search. However, if you want to look for all users, you are going to have to go about this differently however. You have to manually pull the users from the internal MySQL tables.
Changing a user's password
Pretty simple. The passwords are hashed internally in MySQL, so you can't retrieve them, but you can't change them. So you could either do:
<source lang="mysql"> SET PASSWORD FOR 'Zombo'@'localhost' = PASSWORD('newpass'); </source>
Or you can do this by changing the permissions tables directly:
<source lang="mysql"> UPDATE mysql.user SET Password=PASSWORD('newpass')
WHERE User='Zombo' AND Host='localhost';
FLUSH PRIVILEGES; </source>
If you do the second, you have to make sure that you flush privileges however. Forget that, and it won't work.
MySQL 4
Granting Permissions
So, MySQL 4 doesn't have the same users concept. Unfortunately, this means that the users table doesn't work quite the same. Instead, grants work differently, and you have to add them manually.
<source lang="mysql"> GRANT ALL ON mydb.* TO 'someuser'@'somehost' IDENTIFIED BY PASSWORD 'mysecretpass'; FLUSH PRIVILEGES; </source>
Lots of things change on this. However, lots of people are moving away from MySQL 4, so this is quickly becoming a moot point.
Changing Passwords
You can change this too:
mysql> SET PASSWORD FOR 'username'@'localhost' = PASSWORD('$newpass');
Exporting and Importing
You can drop a copy of all grants for a cpanel server to a flat file with the following single command:
mysql -B -N -e "SELECT DISTINCT CONCAT('SHOW GRANTS FOR ''', user, '''@''', host, ''';') AS query FROM mysql.user" | mysql $@ | sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}' | egrep -v '(root|horde|cphulkd|eximstats|modsec|roundcube)' > mysqlprivs.txt
You can change the "egrep" portion of the command to alter what is dumped. So, if you change "egrep -v '(root....)'" to "egrep cpanuser", then you will only get grants for that one user.
Import this dump into mysql on a different server with:
mysql < mysqlprivs.txt
Alright, so you know how to run some MySQL queries. Enough to be dangerous. Let's learn some more.
Also, it's important to keep in mind when configuring MySQL, better to set things up to do something small very well than do a lot of things badly. Keep this in mind when setting things like max connections, timeouts, and similar things. A small mess doing nothing is always better than a big mess doing nothing - much easier to sort out.
MySQL Variables
First, it's important to see all the variables that we're going to look at. So, let's! Don't get overwhelmed!
<source lang='mysql'> mysql> show variables; +-----------------------------------------+---------------------------------------+ | Variable_name | Value | +-----------------------------------------+---------------------------------------+ | auto_increment_increment | 1 | | auto_increment_offset | 1 | | automatic_sp_privileges | ON | | back_log | 50 | | basedir | / | | binlog_cache_size | 32768 | | bulk_insert_buffer_size | 8388608 | | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | | collation_connection | latin1_swedish_ci | | collation_database | latin1_swedish_ci | | collation_server | latin1_swedish_ci | | completion_type | 0 | | concurrent_insert | 1 | | connect_timeout | 10 | | datadir | /var/lib/mysql/ | | date_format | %Y-%m-%d | | datetime_format | %Y-%m-%d %H:%i:%s | | default_week_format | 0 | | delay_key_write | ON | | delayed_insert_limit | 100 | | delayed_insert_timeout | 300 | | delayed_queue_size | 1000 | | div_precision_increment | 4 | | keep_files_on_create | OFF | | engine_condition_pushdown | OFF | | expire_logs_days | 0 | | flush | OFF | | flush_time | 0 | | ft_boolean_syntax | + -><()~*:""&| | | ft_max_word_len | 84 | | ft_min_word_len | 4 | | ft_query_expansion_limit | 20 | | ft_stopword_file | (built-in) | | group_concat_max_len | 1024 | | have_archive | YES | | have_bdb | NO | | have_blackhole_engine | YES | | have_compress | YES | | have_community_features | NO | | have_profiling | NO | | have_crypt | YES | | have_csv | YES | | have_dynamic_loading | YES | | have_example_engine | YES | | have_federated_engine | YES | | have_geometry | YES | | have_innodb | YES | | have_isam | NO | | have_merge_engine | YES | | have_ndbcluster | NO | | have_openssl | NO | | have_ssl | NO | | have_query_cache | YES | | have_raid | NO | | have_rtree_keys | YES | | have_symlink | YES | | hostname | host.jhayhurst.com | | init_connect | | | init_file | | | init_slave | | | innodb_additional_mem_pool_size | 1048576 | | innodb_autoextend_increment | 8 | | innodb_buffer_pool_awe_mem_mb | 0 | | innodb_buffer_pool_size | 8388608 | | innodb_checksums | ON | | innodb_commit_concurrency | 0 | | innodb_concurrency_tickets | 500 | | innodb_data_file_path | ibdata1:10M:autoextend | | innodb_data_home_dir | | | innodb_adaptive_hash_index | ON | | innodb_doublewrite | ON | | innodb_fast_shutdown | 1 | | innodb_file_io_threads | 4 | | innodb_file_per_table | OFF | | innodb_flush_log_at_trx_commit | 1 | | innodb_flush_method | | | innodb_force_recovery | 0 | | innodb_lock_wait_timeout | 50 | | innodb_locks_unsafe_for_binlog | OFF | | innodb_log_arch_dir | | | innodb_log_archive | OFF | | innodb_log_buffer_size | 1048576 | | innodb_log_file_size | 5242880 | | innodb_log_files_in_group | 2 | | innodb_log_group_home_dir | ./ | | innodb_max_dirty_pages_pct | 90 | | innodb_max_purge_lag | 0 | | innodb_mirrored_log_groups | 1 | | innodb_open_files | 300 | | innodb_rollback_on_timeout | OFF | | innodb_support_xa | ON | | innodb_sync_spin_loops | 20 | | innodb_table_locks | ON | | innodb_thread_concurrency | 8 | | innodb_thread_sleep_delay | 10000 | | innodb_use_legacy_cardinality_algorithm | ON | | interactive_timeout | 28800 | | join_buffer_size | 131072 | | key_buffer_size | 16777216 | | key_cache_age_threshold | 300 | | key_cache_block_size | 1024 | | key_cache_division_limit | 100 | | language | /usr/share/mysql/english/ | | large_files_support | ON | | large_page_size | 0 | | large_pages | OFF | | lc_time_names | en_US | | license | GPL | | local_infile | ON | | locked_in_memory | OFF | | log | OFF | | log_bin | OFF | | log_bin_trust_function_creators | OFF | | log_error | | | log_queries_not_using_indexes | OFF | | log_slave_updates | OFF | | log_slow_queries | OFF | | log_warnings | 1 | | long_query_time | 10 | | low_priority_updates | OFF | | lower_case_file_system | OFF | | lower_case_table_names | 0 | | max_allowed_packet | 1048576 | | max_binlog_cache_size | 4294963200 | | max_binlog_size | 1073741824 | | max_connect_errors | 10 | | max_connections | 150 | | max_delayed_threads | 20 | | max_error_count | 64 | | max_heap_table_size | 16777216 | | max_insert_delayed_threads | 20 | | max_join_size | 18446744073709551615 | | max_length_for_sort_data | 1024 | | max_prepared_stmt_count | 16382 | | max_relay_log_size | 0 | | max_seeks_for_key | 4294967295 | | max_sort_length | 1024 | | max_sp_recursion_depth | 0 | | max_tmp_tables | 32 | | max_user_connections | 0 | | max_write_lock_count | 4294967295 | | multi_range_count | 256 | | myisam_data_pointer_size | 6 | | myisam_max_sort_file_size | 2146435072 | | myisam_mmap_size | 4294967295 | | myisam_recover_options | OFF | | myisam_repair_threads | 1 | | myisam_sort_buffer_size | 8388608 | | myisam_stats_method | nulls_unequal | | net_buffer_length | 8192 | | net_read_timeout | 30 | | net_retry_count | 10 | | net_write_timeout | 60 | | new | OFF | | old_passwords | OFF | | open_files_limit | 1024 | | optimizer_prune_level | 1 | | optimizer_search_depth | 62 | | pid_file | /var/lib/mysql/host.jhayhurst.com.pid | | plugin_dir | | | port | 3306 | | preload_buffer_size | 32768 | | protocol_version | 10 | | query_alloc_block_size | 8192 | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 8388608 | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | | query_prealloc_size | 8192 | | range_alloc_block_size | 4096 | | read_buffer_size | 262144 | | read_only | OFF | | read_rnd_buffer_size | 524288 | | relay_log | | | relay_log_index | | | relay_log_info_file | relay-log.info | | relay_log_purge | ON | | relay_log_space_limit | 0 | | rpl_recovery_rank | 0 | | secure_auth | OFF | | secure_file_priv | | | server_id | 0 | | skip_external_locking | ON | | skip_networking | OFF | | skip_show_database | OFF | | slave_compressed_protocol | OFF | | slave_load_tmpdir | /tmp/ | | slave_net_timeout | 3600 | | slave_skip_errors | OFF | | slave_transaction_retries | 10 | | slow_launch_time | 2 | | socket | /var/lib/mysql/mysql.sock | | sort_buffer_size | 524288 | | sql_big_selects | ON | | sql_mode | | | sql_notes | ON | | sql_warnings | OFF | | ssl_ca | | | ssl_capath | | | ssl_cert | | | ssl_cipher | | | ssl_key | | | storage_engine | MyISAM | | sync_binlog | 0 | | sync_frm | ON | | system_time_zone | EST | | table_cache | 64 | | table_lock_wait_timeout | 50 | | table_type | MyISAM | | thread_cache_size | 0 | | thread_stack | 196608 | | time_format | %H:%i:%s | | time_zone | SYSTEM | | timed_mutexes | OFF | | tmp_table_size | 33554432 | | tmpdir | /tmp/ | | transaction_alloc_block_size | 8192 | | transaction_prealloc_size | 4096 | | tx_isolation | REPEATABLE-READ | | updatable_views_with_limit | YES | | version | 5.0.92-community | | version_comment | MySQL Community Edition (GPL) | | version_compile_machine | i686 | | version_compile_os | pc-linux-gnu | | wait_timeout | 28800 | +-----------------------------------------+---------------------------------------+ 233 rows in set (0.00 sec) </source>
That's right. That's all of them. aren't you excited? Now, let's go over some....
auto_increment_*
Alright, so you can set a column to auto_increment on a table. What this means is that when you add a new row, if/when you don't specify a value for that column, it'll fill it in with the next one. auto_increment_increment sets what that goes up by each time (default is 1) and auto_increment_offset sets what that starts numbering with (if not set in the table structure) default is 1.
concurrent_insert
1 is default, and queues inserts up as you would expect. Read more here:
http://dev.mysql.com/doc/refman/5.0/en/concurrent-inserts.html
datadir
This value specifies where the MySQL datadir is. The MySQL datadir in general contains the MySQL database internal information. You want to avoid changing ANYTHING in this directory however, or even creating new files. Everything in here is used/mounted/put up by MySQL, if you put the wrong thing in here, it can cause problems, crashes, data loss, and worse.
delayed_insert*
When you insert/update/delete a row in a table, you can actually tell MySQL to "wait until you're not so busy" and then make the change. Then, if things in MySQL are a bit busier (like let's say everyone decides to SELECT things at the same time) not everybody has to wait right away.
delayed_insert_limit sets the number of rows to insert in a batch before checking to see if more queries are waiting.
delayed_insert_timeout sets how many seconds to wait for more inserts before doing another batch
delayed_queue_size sets the amount of space to reserve for this queue
hostname
This is the hostname of the server, and can't really be set in MySQL (afaik).
innodb_file_per_table
This is the magical setting. By deafult, MySQL puts all InnoDB data in one set of files - ibdata and ib_logfile0/ib_logfile1. Set this, and you now have an .idb file for each MySQL table - if one goes bad, you just have to remove that one. Very helpful.
This CANNOT be changed under normal circumstances. To change this, there has to be NO InnoDB tables. You can either dump all InnoDB tables out, then drop all InnoDB tables, and switch this, then reimport, or you can convert all of these tables to MyISAM, switch this, then switch them back.
interactive_timeout
This is the magical MySQL setting that you want to change. Sometimes people have a lot of MySQL queries that are stacking up. By setting this lowere, you can prevent them from stacking up. A smaller mess that's not doing anything is always better than a bigger mess that isn't doing anything.
join_buffer_size
When MySQL does a JOIN as a part of a query, it takes the two tables and finds out where they line up, and how. This takes some work. This setting lets you set the size of a buffer that saves the result of this work, and reuses it when it can.
key_buffer_size
Similar to above, but this one caches the table keys.
low_priority_updates
This is related to delayed inserts above. This makes updates low priority, often very useful.
lower_case_table_names
This one's more useful on older Windows systems, where the letters 'A' and 'a' are the same. It only lets you create tables with lower case characters, if you put in a query with any upper case letters in it, it'll get translated to lower case characters before being executed. This is a bit of a pain when you have a table with a upper case character in the table name, you can't touch that table.
max_allowed_packet
This one sets the maximum size of a MySQL query that come into MySQL, or the max length of the query.
max_connections
How many concurrent connections can you have? Remember, better to set this low, get things stable, and keep this low. Caching queries outside of MySQL often helps an application, particularly if the application's heavy on requesting the same information.
pid_file
This is the location of the MySQL PID file.
port
Port that MySQL is running on.
query_cache_size
MySQL can cache complete result sets for SELECT statements via this directive.
"The MySQL query cache holds the exact bits that a completed query returned to the client. When a query cache hit occurs, the server can simply return the stored results immediately, skipping the parsing, optimization, and execution steps.
The query cache is designed to be completely transparent to the application. The application does not need to know whether MySQL returned data from the cache or actually executed the query. As servers have gotten larger and more powerful, the query cache has unfortunately proven not to be a very scalable part of MySQL. It is effectively a single point of contention for the whole server, and it can cause severe stalls on multicore servers.
The query cache can still be a net gain. However, the extra overhead can add up, especially in combination with contention caused by queries trying to lock the cache to perform operations on it. For InnoDB users, another problem is that transactions limit the query cache’s usefulness. When a statement inside a transaction modifies a table, the server invalidates any cached queries that refer to the table, even though InnoDB’s multiversioning might hide the transaction’s changes from other statements. The table is also globally uncacheable until the transaction commits, so no further queries against that table - whether inside or outside the transaction—can be cached until the transaction commits. Long-running transactions can, therefore, increase the number of query cache misses."
--High Performance MySQL 3rd edition - Baron Schwartz, Peter Zaitsev, Vadim Tkachenko, Jeremy Zawodny, Arjen Lentz, Derek Balling
query_cache_wlock_invalidate
Considering the risk of contention with locked tables, you may want to experiment with a value of ON or OFF to see if cache invalidation is a factor. Setting this to the non-default value ON can cause higher wait lock times, but can ensure that results are not coming from the query cache if the table has been locked.
sort_buffer_size
You'd be better off optmizing your queries rather than trying to finesse performance out of the sorting operation itself. Setting this to more than 2MB should never happen. Our wiki "opts" have this set to 2MB, but anything more than 256k will give diminishing returns. This is due to memory allocation on behalf of the OS changing from mmap() to malloc() if 256k is exceeded. Tests have shown malloc() to 37x slower in similar use cases.
read_only
Only allows Super user to make changes to databases if this is set.
table_lock_wait_timeout
How long to try to get a table lock before kicking an error.
time_zone
MySQL time zone, if set to SYSTEM time zone is inherited on MySQL startup.
tmpdir
Location for MySQL to put tempoary tables that it needs to write to disk, or it's "saved work" that it's doing. For instance, if this is on a 1G partition (like /tmp) and you repair or optimize a 2G table, it needs to put this table somewhere while it's fixing it. There won't be enough room, and you'll run into problems. This location needs to be readable, writable, and executable by MySQL.
version
Show's MySQL server version. Remember, there's a MySQL server, and mysqlclient. When you type mysql on the command line, you're using the mysql client to connect to the MySQL server.
wait_timeout
This sets how long to wait on a query that's marked itself as waiting before killing the query.
Show Status
You probably don't care about most of these. But there is useful stuff in this one, so give it a try sometime.
<source lang="mysql"> mysql> show status; </source>
There may be some interesting things in here, this is mostly where status related things are stored.
Can be helpful, if you're working on certain things.
mysqltuner
This is covered in so much awesome sauce. SOOOO MUCH AWESOME SAUCE.
But you have to understand what you're doing with each, and understand what it's telling you.
GRANT TRIGGER PERMISSION
Triggers have to be granted by table. Example.
mysql> SHOW GRANTS FOR 'devcred'@'%';
no trigger priv found
mysql> GRANT Trigger ON TABLE devcred_civicrm.abc TO mysql> 'devcred'@'%'; Query OK, 0 rows affected (0.01 sec)
mysql> SHOW GRANTS FOR 'devcred'@'%';
| GRANT TRIGGER ON `devcred_civicrm`.`abc` TO 'devcred'@'%'