MySQL Tipps und Tricks: Difference between revisions
m (Text replacement - "</source" to "</syntaxhighlight") |
|||
Line 14: | Line 14: | ||
} | } | ||
}' | }' | ||
</ | </syntaxhighlight> | ||
===Mysql processes each second=== | ===Mysql processes each second=== | ||
<source lang=bash> | <source lang=bash> | ||
# mysqladmin -i 1 --verbose processlist | # mysqladmin -i 1 --verbose processlist | ||
</ | </syntaxhighlight> | ||
===All grants=== | ===All grants=== | ||
<source lang=bash> | <source lang=bash> | ||
# mysql --skip-column-names --batch --execute 'select concat("`",user,"`@`",host,"`") from mysql.user' | xargs -n 1 -i mysql --execute 'show grants for {}' | # mysql --skip-column-names --batch --execute 'select concat("`",user,"`@`",host,"`") from mysql.user' | xargs -n 1 -i mysql --execute 'show grants for {}' | ||
</ | </syntaxhighlight> | ||
Or a little nicer: | Or a little nicer: | ||
Line 162: | Line 162: | ||
done | done | ||
done | done | ||
</ | </syntaxhighlight> | ||
===Last update time=== | ===Last update time=== | ||
Line 168: | Line 168: | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SELECT TABLE_SCHEMA AS DB,TABLE_NAME,UPDATE_TIME FROM INFORMATION_SCHEMA.TABLES ORDER BY DB,UPDATE_TIME; | mysql> SELECT TABLE_SCHEMA AS DB,TABLE_NAME,UPDATE_TIME FROM INFORMATION_SCHEMA.TABLES ORDER BY DB,UPDATE_TIME; | ||
</ | </syntaxhighlight> | ||
* Per database | * Per database | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SELECT TABLE_SCHEMA AS DB,MAX(UPDATE_TIME) AS LAST_UPDATE FROM INFORMATION_SCHEMA.TABLES GROUP BY DB ORDER BY LAST_UPDATE; | mysql> SELECT TABLE_SCHEMA AS DB,MAX(UPDATE_TIME) AS LAST_UPDATE FROM INFORMATION_SCHEMA.TABLES GROUP BY DB ORDER BY LAST_UPDATE; | ||
</ | </syntaxhighlight> | ||
==InnoDB space== | ==InnoDB space== | ||
Line 179: | Line 179: | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> select table_schema as database_name, sum(round(data_length/1024/1024,2)) as total_size_mb from information_schema.tables where engine like 'innodb' group by table_schema order by total_size_mb; | mysql> select table_schema as database_name, sum(round(data_length/1024/1024,2)) as total_size_mb from information_schema.tables where engine like 'innodb' group by table_schema order by total_size_mb; | ||
</ | </syntaxhighlight> | ||
===Per table=== | ===Per table=== | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> select table_schema as database_name,table_name,round(data_length/1024/1024,2) as size_mb from information_schema.tables order by size_mb; | mysql> select table_schema as database_name,table_name,round(data_length/1024/1024,2) as size_mb from information_schema.tables order by size_mb; | ||
</ | </syntaxhighlight> | ||
==Logging== | ==Logging== | ||
Line 206: | Line 206: | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL log_output=TABLE; | mysql> SET GLOBAL log_output=TABLE; | ||
</ | </syntaxhighlight> | ||
* Log to the table mysql.slow_log and mysql.general_log | * Log to the table mysql.slow_log and mysql.general_log | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL log_output=TABLE; | mysql> SET GLOBAL log_output=TABLE; | ||
</ | </syntaxhighlight> | ||
* Both: tables and files | * Both: tables and files | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL log_output = 'TABLE,FILE'; | mysql> SET GLOBAL log_output = 'TABLE,FILE'; | ||
</ | </syntaxhighlight> | ||
* None, if NONE appears in the log_output destinations there is no logging | * None, if NONE appears in the log_output destinations there is no logging | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL log_output = 'TABLE,FILE,NONE'; | mysql> SET GLOBAL log_output = 'TABLE,FILE,NONE'; | ||
</ | </syntaxhighlight> | ||
is equal to | is equal to | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL log_output = 'NONE'; | mysql> SET GLOBAL log_output = 'NONE'; | ||
</ | </syntaxhighlight> | ||
===Enable/disable general logging=== | ===Enable/disable general logging=== | ||
Line 234: | Line 234: | ||
mysql> SET GLOBAL general_log = 'ON'; | mysql> SET GLOBAL general_log = 'ON'; | ||
Query OK, 0 rows affected (0.00 sec) | Query OK, 0 rows affected (0.00 sec) | ||
</ | </syntaxhighlight> | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL general_log = 'OFF'; | mysql> SET GLOBAL general_log = 'OFF'; | ||
Query OK, 0 rows affected (0.00 sec) | Query OK, 0 rows affected (0.00 sec) | ||
</ | </syntaxhighlight> | ||
===Enable/disable logging of slow queries=== | ===Enable/disable logging of slow queries=== | ||
Line 248: | Line 248: | ||
mysql> SET GLOBAL slow_query_log = 'ON'; | mysql> SET GLOBAL slow_query_log = 'ON'; | ||
Query OK, 0 rows affected (0.00 sec) | Query OK, 0 rows affected (0.00 sec) | ||
</ | </syntaxhighlight> | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SET GLOBAL slow_query_log = 'OFF'; | mysql> SET GLOBAL slow_query_log = 'OFF'; | ||
Query OK, 0 rows affected (0.00 sec) | Query OK, 0 rows affected (0.00 sec) | ||
</ | </syntaxhighlight> | ||
== Slave == | == Slave == | ||
Line 261: | Line 261: | ||
<source lang=bash> | <source lang=bash> | ||
# mysqlbinlog --read-from-remote-server --host='your replication host' --user='your replication user' --password='your replication password' --base64-output=auto --database='limit output to this database' -vv mysql-bin.number | less | # mysqlbinlog --read-from-remote-server --host='your replication host' --user='your replication user' --password='your replication password' --base64-output=auto --database='limit output to this database' -vv mysql-bin.number | less | ||
</ | </syntaxhighlight> | ||
if you get | if you get | ||
ERROR: Failed on connect: SSL connection error: protocol version mismatch | ERROR: Failed on connect: SSL connection error: protocol version mismatch | ||
Line 267: | Line 267: | ||
<source lang=bash> | <source lang=bash> | ||
# mysqlbinlog --read-from-remote-server --host='your replication host' --user='your replication user' --password='your replication password' --ssl-mode=DISABLED --base64-output=auto --database='limit output to this database' -vv mysql-bin.number | less | # mysqlbinlog --read-from-remote-server --host='your replication host' --user='your replication user' --password='your replication password' --ssl-mode=DISABLED --base64-output=auto --database='limit output to this database' -vv mysql-bin.number | less | ||
</ | </syntaxhighlight> | ||
For an idea of the binlog file to investigate on the master do this on your slave: | For an idea of the binlog file to investigate on the master do this on your slave: | ||
<source lang=bash> | <source lang=bash> | ||
# mysql -e 'show slave status\G' | awk '$1=="Master_Log_File:"' | # mysql -e 'show slave status\G' | awk '$1=="Master_Log_File:"' | ||
</ | </syntaxhighlight> | ||
==Filesystems for MySQL== | ==Filesystems for MySQL== | ||
Line 280: | Line 280: | ||
<source lang=bash> | <source lang=bash> | ||
# mkfs.ext4 -b 4096 /dev/mapper/vg--data-lv--ext4--mysql_data | # mkfs.ext4 -b 4096 /dev/mapper/vg--data-lv--ext4--mysql_data | ||
</ | </syntaxhighlight> | ||
====Mountoptions==== | ====Mountoptions==== | ||
Line 297: | Line 297: | ||
# ls -alL /dev/vg-data/lv-rawdisk-innodb01 | # ls -alL /dev/vg-data/lv-rawdisk-innodb01 | ||
brw-rw---- 1 mysql mysql 252, 0 Aug 12 15:07 /dev/vg-data/lv-rawdisk-innodb01 | brw-rw---- 1 mysql mysql 252, 0 Aug 12 15:07 /dev/vg-data/lv-rawdisk-innodb01 | ||
</ | </syntaxhighlight> | ||
Determine the size: | Determine the size: | ||
Line 317: | Line 317: | ||
26843545600/(1024*1024*1024) | 26843545600/(1024*1024*1024) | ||
25.00000000000000000000 | 25.00000000000000000000 | ||
</ | </syntaxhighlight> | ||
Yes... really 25GB! | Yes... really 25GB! | ||
Line 326: | Line 326: | ||
innodb_data_home_dir= | innodb_data_home_dir= | ||
innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Gnewraw | innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Gnewraw | ||
</ | </syntaxhighlight> | ||
Start mysql: | Start mysql: | ||
<source lang=bash> | <source lang=bash> | ||
# service mysql start | # service mysql start | ||
</ | </syntaxhighlight> | ||
Aaaaaand.. do not forget apparmor! Like I did.. :-D | Aaaaaand.. do not forget apparmor! Like I did.. :-D | ||
Line 341: | Line 341: | ||
InnoDB: File operation call: 'open'. | InnoDB: File operation call: 'open'. | ||
InnoDB: Cannot continue operation. | InnoDB: Cannot continue operation. | ||
</ | </syntaxhighlight> | ||
<source lang=bash> | <source lang=bash> | ||
Line 348: | Line 348: | ||
Aug 12 15:30:09 mysql kernel: [ 5840.118528] audit: type=1400 audit(1439386209.399:33): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/dev/dm-0" pid=11810 comm="mysqld" requested_mask="wr" denied_mask="wr" fsuid=108 ouid=108 | Aug 12 15:30:09 mysql kernel: [ 5840.118528] audit: type=1400 audit(1439386209.399:33): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/dev/dm-0" pid=11810 comm="mysqld" requested_mask="wr" denied_mask="wr" fsuid=108 ouid=108 | ||
... | ... | ||
</ | </syntaxhighlight> | ||
Add your raw device to the apparmor config in /etc/apparmor.d/local/usr.sbin.mysqld : | Add your raw device to the apparmor config in /etc/apparmor.d/local/usr.sbin.mysqld : | ||
<source lang=bash> | <source lang=bash> | ||
Line 354: | Line 354: | ||
# For more details, please see /etc/apparmor.d/local/README. | # For more details, please see /etc/apparmor.d/local/README. | ||
/dev/dm-* rwk, | /dev/dm-* rwk, | ||
</ | </syntaxhighlight> | ||
Reload apparmor: | Reload apparmor: | ||
<source lang=bash> | <source lang=bash> | ||
# service apparmor reload | # service apparmor reload | ||
</ | </syntaxhighlight> | ||
Another try! | Another try! | ||
<source lang=bash> | <source lang=bash> | ||
# service mysql start | # service mysql start | ||
</ | </syntaxhighlight> | ||
<source lang=mysql> | <source lang=mysql> | ||
Line 372: | Line 372: | ||
InnoDB: Database physically writes the file full: wait... | InnoDB: Database physically writes the file full: wait... | ||
InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 1100 1200 ... | InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 1100 1200 ... | ||
</ | </syntaxhighlight> | ||
Much better! | Much better! | ||
Line 384: | Line 384: | ||
innodb_data_home_dir= | innodb_data_home_dir= | ||
innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Graw | innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Graw | ||
</ | </syntaxhighlight> | ||
=== NFS === | === NFS === | ||
Line 403: | Line 403: | ||
cdot1nfsv4 MYSQLNFS_LOG 1GB mysql_clients /MYSQLNFS_LOG | cdot1nfsv4 MYSQLNFS_LOG 1GB mysql_clients /MYSQLNFS_LOG | ||
2 entries were displayed. | 2 entries were displayed. | ||
</ | </syntaxhighlight> | ||
Links: | Links: | ||
Line 418: | Line 418: | ||
# echo "blacklist rpcsec_gss_krb5" > /etc/modprobe.d/blacklist-rpcsec_gss_krb5.conf | # echo "blacklist rpcsec_gss_krb5" > /etc/modprobe.d/blacklist-rpcsec_gss_krb5.conf | ||
# rmmod rpcsec_gss_krb5 | # rmmod rpcsec_gss_krb5 | ||
</ | </syntaxhighlight> | ||
====== /etc/sysctl.d/99-mysql.conf ====== | ====== /etc/sysctl.d/99-mysql.conf ====== | ||
Line 437: | Line 437: | ||
vm.swappiness = 0 | vm.swappiness = 0 | ||
vm.vfs_cache_pressure = 50 | vm.vfs_cache_pressure = 50 | ||
</ | </syntaxhighlight> | ||
====== /etc/sysctl.d/99-netapp-nfs.conf ====== | ====== /etc/sysctl.d/99-netapp-nfs.conf ====== | ||
Line 484: | Line 484: | ||
net.ipv4.neigh.default.base_reachable_time = 86400 | net.ipv4.neigh.default.base_reachable_time = 86400 | ||
net.ipv4.neigh.default.gc_stale_time = 86400 | net.ipv4.neigh.default.gc_stale_time = 86400 | ||
</ | </syntaxhighlight> | ||
Line 495: | Line 495: | ||
mysql soft nproc 10240 | mysql soft nproc 10240 | ||
mysql hard nproc 10240 | mysql hard nproc 10240 | ||
</ | </syntaxhighlight> | ||
====== Modify systemd mysql.service to raise the number of files limit ====== | ====== Modify systemd mysql.service to raise the number of files limit ====== | ||
Line 502: | Line 502: | ||
<source lang=bash> | <source lang=bash> | ||
# systemctl edit mysql.service | # systemctl edit mysql.service | ||
</ | </syntaxhighlight> | ||
and enter: | and enter: | ||
<source lang=ini> | <source lang=ini> | ||
[Service] | [Service] | ||
LimitNOFILE=1024000 | LimitNOFILE=1024000 | ||
</ | </syntaxhighlight> | ||
<source lang=bash> | <source lang=bash> | ||
# systemctl cat mysql | # systemctl cat mysql | ||
Line 516: | Line 516: | ||
[Service] | [Service] | ||
LimitNOFILE=1024000 | LimitNOFILE=1024000 | ||
</ | </syntaxhighlight> | ||
Do not forget to activate and check the limit | Do not forget to activate and check the limit | ||
Line 525: | Line 525: | ||
Limit Soft Limit Hard Limit Units | Limit Soft Limit Hard Limit Units | ||
Max open files 1024000 1024000 files | Max open files 1024000 1024000 files | ||
</ | </syntaxhighlight> | ||
====== Modify systemd service to wait for NFS ====== | ====== Modify systemd service to wait for NFS ====== | ||
Line 532: | Line 532: | ||
<source lang=bash> | <source lang=bash> | ||
# systemctl edit mysql.service | # systemctl edit mysql.service | ||
</ | </syntaxhighlight> | ||
and enter: | and enter: | ||
<source lang=ini> | <source lang=ini> | ||
Line 539: | Line 539: | ||
After=network.target | After=network.target | ||
After=nfs-client.target | After=nfs-client.target | ||
</ | </syntaxhighlight> | ||
<source lang=bash> | <source lang=bash> | ||
Line 573: | Line 573: | ||
[Service] | [Service] | ||
LimitNOFILE=1024000 | LimitNOFILE=1024000 | ||
</ | </syntaxhighlight> | ||
Do not forget to activate the changes... | Do not forget to activate the changes... | ||
Line 579: | Line 579: | ||
# systemctl daemon-reload | # systemctl daemon-reload | ||
# systemctl restart mysql | # systemctl restart mysql | ||
</ | </syntaxhighlight> | ||
... and check they are active: | ... and check they are active: | ||
Line 585: | Line 585: | ||
# systemctl list-dependencies --after mysql.service | grep nfs-client.target | # systemctl list-dependencies --after mysql.service | grep nfs-client.target | ||
● ├─nfs-client.target | ● ├─nfs-client.target | ||
</ | </syntaxhighlight> | ||
====== /etc/idmapd.conf ====== | ====== /etc/idmapd.conf ====== | ||
Line 591: | Line 591: | ||
# Domain = localdomain | # Domain = localdomain | ||
Domain = this.domain.tld | Domain = this.domain.tld | ||
</ | </syntaxhighlight> | ||
====== /etc/fstab ====== | ====== /etc/fstab ====== | ||
Line 597: | Line 597: | ||
cdot-nfsv4-svm:/MYSQLNFS_LOG /MYSQLNFS_LOG nfs rw,hard,nointr,rsize=65536,wsize=65536,bg,vers=4,proto=tcp,noatime | cdot-nfsv4-svm:/MYSQLNFS_LOG /MYSQLNFS_LOG nfs rw,hard,nointr,rsize=65536,wsize=65536,bg,vers=4,proto=tcp,noatime | ||
cdot-nfsv4-svm:/MYSQLNFS_DATA /MYSQLNFS_DATA nfs rw,hard,nointr,rsize=65536,wsize=65536,bg,vers=4,proto=tcp,noatime | cdot-nfsv4-svm:/MYSQLNFS_DATA /MYSQLNFS_DATA nfs rw,hard,nointr,rsize=65536,wsize=65536,bg,vers=4,proto=tcp,noatime | ||
</ | </syntaxhighlight> | ||
====== /etc/mysql/mysql.conf.d/mysqld.cnf ====== | ====== /etc/mysql/mysql.conf.d/mysqld.cnf ====== | ||
<source lang=ini> | <source lang=ini> | ||
Line 604: | Line 604: | ||
datadir = /MYSQLNFS_DATA/data/mysql | datadir = /MYSQLNFS_DATA/data/mysql | ||
... | ... | ||
</ | </syntaxhighlight> | ||
====== /etc/mysql/mysql.conf.d/innodb.cnf ====== | ====== /etc/mysql/mysql.conf.d/innodb.cnf ====== | ||
Line 618: | Line 618: | ||
innodb_flush_log_at_trx_commit = 2 | innodb_flush_log_at_trx_commit = 2 | ||
innodb_file_per_table = on | innodb_file_per_table = on | ||
</ | </syntaxhighlight> | ||
<source lang=mysql> | <source lang=mysql> | ||
# mysql -e "show variables where variable_name like '%dir' and value like '/MYSQLNFS%'" | # mysql -e "show variables where variable_name like '%dir' and value like '/MYSQLNFS%'" | ||
Line 628: | Line 628: | ||
| innodb_log_group_home_dir | /MYSQLNFS_LOG/ib_log | | | innodb_log_group_home_dir | /MYSQLNFS_LOG/ib_log | | ||
+---------------------------+------------------------------------+ | +---------------------------+------------------------------------+ | ||
</ | </syntaxhighlight> | ||
====== /etc/mysql/mysql.conf.d/query_cache.cnf ====== | ====== /etc/mysql/mysql.conf.d/query_cache.cnf ====== | ||
<source lang=ini> | <source lang=ini> | ||
Line 639: | Line 639: | ||
query_cache_min_res_unit = 2k | query_cache_min_res_unit = 2k | ||
query_cache_size = 80M | query_cache_size = 80M | ||
</ | </syntaxhighlight> | ||
<source lang=mysql> | <source lang=mysql> | ||
Line 661: | Line 661: | ||
+------------------------------+----------+ | +------------------------------+----------+ | ||
5 rows in set (0,00 sec) | 5 rows in set (0,00 sec) | ||
</ | </syntaxhighlight> | ||
====== apparmor : /etc/apparmor.d/local/usr.sbin.mysqld ====== | ====== apparmor : /etc/apparmor.d/local/usr.sbin.mysqld ====== | ||
Line 679: | Line 679: | ||
/MYSQLNFS_LOG/ r, | /MYSQLNFS_LOG/ r, | ||
/MYSQLNFS_LOG/** rwk, | /MYSQLNFS_LOG/** rwk, | ||
</ | </syntaxhighlight> | ||
====== Short stupid performance test ====== | ====== Short stupid performance test ====== | ||
Line 691: | Line 691: | ||
user 0m0.016s | user 0m0.016s | ||
sys 0m0.672s | sys 0m0.672s | ||
</ | </syntaxhighlight> | ||
Some things seem to work... | Some things seem to work... | ||
Line 724: | Line 724: | ||
innodb_log_file_size=100M | innodb_log_file_size=100M | ||
innodb_log_group_home_dir=/var/lib/mysql/ib_log | innodb_log_group_home_dir=/var/lib/mysql/ib_log | ||
</ | </syntaxhighlight> | ||
==Analyze== | ==Analyze== | ||
Line 730: | Line 730: | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> select * from <tablename> PROCEDURE ANALYSE(); | mysql> select * from <tablename> PROCEDURE ANALYSE(); | ||
</ | </syntaxhighlight> | ||
<source lang=mysql> | <source lang=mysql> | ||
mysql> SHOW /*!50000 GLOBAL*/ STATUS; | mysql> SHOW /*!50000 GLOBAL*/ STATUS; | ||
</ | </syntaxhighlight> | ||
* See [[http://de.slideshare.net/shinguz/pt-presentation-11465700 MySQL Performance Tuning]] | * See [[http://de.slideshare.net/shinguz/pt-presentation-11465700 MySQL Performance Tuning]] | ||
Line 746: | Line 746: | ||
MESSAGE_TEXT: No database selected | MESSAGE_TEXT: No database selected | ||
1 row in set (0,00 sec) | 1 row in set (0,00 sec) | ||
</ | </syntaxhighlight> | ||
Line 770: | Line 770: | ||
+- Table | +- Table | ||
table user | table user | ||
</ | </syntaxhighlight> | ||
===Sysbench=== | ===Sysbench=== | ||
Line 800: | Line 800: | ||
run | run | ||
# mysql -u root_rw -e "drop table sbtest;" sbtest | # mysql -u root_rw -e "drop table sbtest;" sbtest | ||
</ | </syntaxhighlight> | ||
==Recover a damaged root account== | ==Recover a damaged root account== | ||
Line 813: | Line 813: | ||
# rm /root/mysql-init | # rm /root/mysql-init | ||
# service mysql start | # service mysql start | ||
</ | </syntaxhighlight> | ||
Or: | Or: | ||
<source lang=bash> | <source lang=bash> | ||
Line 822: | Line 822: | ||
# mysqladmin -u root shutdown | # mysqladmin -u root shutdown | ||
# service mysql start | # service mysql start | ||
</ | </syntaxhighlight> | ||
===Lost password=== | ===Lost password=== | ||
Line 833: | Line 833: | ||
# rm /root/mysql-init | # rm /root/mysql-init | ||
# service mysql start | # service mysql start | ||
</ | </syntaxhighlight> | ||
==Structured configuration== | ==Structured configuration== | ||
Line 845: | Line 845: | ||
# | # | ||
!includedir /etc/mysql/conf.d/ | !includedir /etc/mysql/conf.d/ | ||
</ | </syntaxhighlight> | ||
/etc/mysql/conf.d/innodb.cnf: | /etc/mysql/conf.d/innodb.cnf: | ||
Line 877: | Line 877: | ||
innodb_log_file_size=100M | innodb_log_file_size=100M | ||
innodb_log_group_home_dir=/var/lib/mysql/ib_log | innodb_log_group_home_dir=/var/lib/mysql/ib_log | ||
</ | </syntaxhighlight> | ||
/etc/mysql/conf.d/myisam.cnf: | /etc/mysql/conf.d/myisam.cnf: | ||
Line 901: | Line 901: | ||
# | # | ||
myisam_use_mmap=1 | myisam_use_mmap=1 | ||
</ | </syntaxhighlight> | ||
/etc/mysql/conf.d/mysqld.cnf: | /etc/mysql/conf.d/mysqld.cnf: | ||
Line 960: | Line 960: | ||
performance_schema = ON | performance_schema = ON | ||
</ | </syntaxhighlight> | ||
/etc/mysql/conf.d/mysqld_safe.cnf: | /etc/mysql/conf.d/mysqld_safe.cnf: | ||
<source lang=mysql> | <source lang=mysql> | ||
[mysqld_safe] | [mysqld_safe] | ||
</ | </syntaxhighlight> | ||
/etc/mysql/conf.d/mysqld_safe_syslog.cnf: | /etc/mysql/conf.d/mysqld_safe_syslog.cnf: | ||
Line 971: | Line 971: | ||
[mysqld_safe] | [mysqld_safe] | ||
syslog | syslog | ||
</ | </syntaxhighlight> | ||
/etc/mysql/conf.d/query_cache.cnf: | /etc/mysql/conf.d/query_cache.cnf: | ||
Line 979: | Line 979: | ||
query_cache_size = 128M | query_cache_size = 128M | ||
query_cache_min_res_unit = 2K | query_cache_min_res_unit = 2K | ||
</ | </syntaxhighlight> | ||
=MySQL Clients= | =MySQL Clients= | ||
Line 1,000: | Line 1,000: | ||
$pdo=null; | $pdo=null; | ||
' | ' | ||
</ | </syntaxhighlight> |
Revision as of 15:22, 25 November 2021
Oneliner
Show MySQL-traffic fired from a client
<source lang=bash>
- tcpdump -i any -s 0 -l -vvv -w - dst port 3306 | strings | perl -e '
while(<>) { chomp; next if /^[^ ]+[ ]*$/;
if(/^(SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER)/i) { if (defined $q) { print "$q\n"; } $q=$_; } else { $_ =~ s/^[ \t]+//; $q.=" $_"; }
}' </syntaxhighlight>
Mysql processes each second
<source lang=bash>
- mysqladmin -i 1 --verbose processlist
</syntaxhighlight>
All grants
<source lang=bash>
- mysql --skip-column-names --batch --execute 'select concat("`",user,"`@`",host,"`") from mysql.user' | xargs -n 1 -i mysql --execute 'show grants for {}'
</syntaxhighlight>
Or a little nicer: <source lang=bash>
- !/bin/bash
-
- Written by Lars Timmann <L@rs.Timmann.de> 2017
function usage () {
cat << EOH
Usage: $0 [--all] [--grant-user <pattern>|--gu <pattern>] [--grant-db <pattern>|--gdb <pattern>] [--help] ...
--help: This output
--grant-user|--gu: You can specify this option several times.
The <pattern> can be: <user> : You will get grants on all hosts for this user. @<host> : You will get grants for all users on this host. <user>@<host> : You will get specific grants for user@host. The pattern may contain % as wildcard. If the pattern is @% it shows all grants where host is exactly '%'. --grant-db|--gdb: You can specify this option several times. The pattern names the database to look for. The pattern may contain % as wildcard. --all: Show all grants ...: Optional parameters to the mysql command
EOH
exit
}
show_all_grants=0 declare -a grant_user for ((param=1;param<=${#};param++)) do
case ${!param} in --grant-user|--gu) param=$[ ${param} + 1 ] grant_user+=( "${!param}" ) # delete 2 parameters from list and set back $param set -- "${@:1:param-2}" "${@:param+1}" param=$[ ${param} - 2 ] ;; --grant-db|--gdb) param=$[ ${param} + 1 ] grant_db+=( "${!param}" ) # delete 2 parameters from list and set back $param set -- "${@:1:param-2}" "${@:param+1}" param=$[ ${param} - 2 ] ;; --all) show_all_grants=1 # delete 1 parameter from list and set back $param set -- "${@:1:param-1}" "${@:param+1}" param=$[ ${param} - 1 ] ;; --help) usage ;; *) ;; esac
done
count=${#grant_user[@]} for((param=0;param<count;param++)) do
before=${#grant_user[@]} grant="${grant_user[${param}]}" user="${grant%@*}" if [[ "${grant}" == *\@?* ]] then host="${grant/*@}" else host= fi case ${host} in ) select="select concat('\,user,'\'@\,host,'\) as user from mysql.user where user like '${user}'" ;; '%') select="select concat('\,user,'\'@\,host,'\) as user from mysql.user where host='${host}' ${user:+and user like '${user}'}" ;; *) select="select concat('\,user,'\'@\,host,'\) as user from mysql.user where host like '${host}' ${user:+and user like '${user}'}" ;; esac grant_user=( "${grant_user[@]:0:param}" $(mysql $* --silent --skip-column-names --execute "${select}" | sort ) "${grant_user[@]:param+1}" ) after=${#grant_user[@]} param=$[ param + after - before ] count=$[ count + after - before ]
done
- Get user for database in grant_db array
for db in ${grant_db[@]} do
grant_user+=( $(mysql $* --silent --skip-column-names --execute " select concat('\,user,'\'@\,host,'\) as user from mysql.db where db like '${db}'; select concat('\,user,'\'@\,host,'\) as user from mysql.columns_priv where db like '${db}'; select concat('\,user,'\'@\,host,'\) as user from mysql.tables_priv where db like '${db}'; " | sort -u ) )
done
- --all
if [ ${show_all_grants} -eq 1 ] then
printf -- '--\n-- %s\n--\n' "all grants"; grant_user=( $(mysql $* --silent --skip-column-names --execute "select concat('\,user,'\'@\,host,'\) as user from mysql.user" | sort ) )
fi
for user in ${grant_user[@]} do
printf -- '--\n-- %s\n--\n' "${user}"; show_create_user="$(mysql $* --silent --skip-column-names --execute "select (substring_index(version(), '.',1) >= 5) and (substring_index(substring_index(version(), '.', 2),'.',-1) >=7) as show_create_user;";)" if [ "${show_create_user}" -eq 1 ] then mysql $* --silent --skip-column-names --execute "show create user ${user};" | sed 's/$/;/' fi OLD_IFS=${IFS} IFS=$'\n' for grant in $(mysql $* --silent --skip-column-names --execute "show grants for ${user}" | sed 's/$/;/') do regex='GRANT[ ]+.*[ ]+ON[ ]+(FUNCTION[ ]+|)`([^`]*)`\..*' if $grant =~ $regex then database=${BASH_REMATCH[2]} if [ ${#grant_db[@]} -gt 0 ] then
if [[ " ${grant_db[@]} " =~ " ${database} " ]]
then
echo "${grant}" fi
else echo "${grant}" fi else echo "${grant}" fi done
done </syntaxhighlight>
Last update time
- Per table
<source lang=mysql> mysql> SELECT TABLE_SCHEMA AS DB,TABLE_NAME,UPDATE_TIME FROM INFORMATION_SCHEMA.TABLES ORDER BY DB,UPDATE_TIME; </syntaxhighlight>
- Per database
<source lang=mysql> mysql> SELECT TABLE_SCHEMA AS DB,MAX(UPDATE_TIME) AS LAST_UPDATE FROM INFORMATION_SCHEMA.TABLES GROUP BY DB ORDER BY LAST_UPDATE; </syntaxhighlight>
InnoDB space
Per database
<source lang=mysql> mysql> select table_schema as database_name, sum(round(data_length/1024/1024,2)) as total_size_mb from information_schema.tables where engine like 'innodb' group by table_schema order by total_size_mb; </syntaxhighlight>
Per table
<source lang=mysql> mysql> select table_schema as database_name,table_name,round(data_length/1024/1024,2) as size_mb from information_schema.tables order by size_mb; </syntaxhighlight>
Logging
If you use SET GLOBAL it is just for the moment.
Don't forget to add it in your my.cnf to make it permanent!
What can I log?
The interesting variables here are:
- log_queries_not_using_indexes
- log_slave_updates
- log_slow_queries
- general_log
Choose logging destination FILE/TABLE/NONE
This affects general_log and slow_query_log.
- Log to the table mysql.slow_log and mysql.general_log
<source lang=mysql> mysql> SET GLOBAL log_output=TABLE; </syntaxhighlight>
- Log to the table mysql.slow_log and mysql.general_log
<source lang=mysql> mysql> SET GLOBAL log_output=TABLE; </syntaxhighlight>
- Both: tables and files
<source lang=mysql> mysql> SET GLOBAL log_output = 'TABLE,FILE'; </syntaxhighlight>
- None, if NONE appears in the log_output destinations there is no logging
<source lang=mysql> mysql> SET GLOBAL log_output = 'TABLE,FILE,NONE'; </syntaxhighlight> is equal to <source lang=mysql> mysql> SET GLOBAL log_output = 'NONE'; </syntaxhighlight>
Enable/disable general logging
<source lang=mysql> mysql> SET GLOBAL general_log_file = '/var/lib/mysql/general.log'; Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL general_log = 'ON'; Query OK, 0 rows affected (0.00 sec) </syntaxhighlight>
<source lang=mysql> mysql> SET GLOBAL general_log = 'OFF'; Query OK, 0 rows affected (0.00 sec) </syntaxhighlight>
Enable/disable logging of slow queries
<source lang=mysql> mysql> SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow-query.log'; Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL slow_query_log = 'ON'; Query OK, 0 rows affected (0.00 sec) </syntaxhighlight>
<source lang=mysql> mysql> SET GLOBAL slow_query_log = 'OFF'; Query OK, 0 rows affected (0.00 sec) </syntaxhighlight>
Slave
Debugging
What did we see from the master
Read the binlog from Master: <source lang=bash>
- mysqlbinlog --read-from-remote-server --host='your replication host' --user='your replication user' --password='your replication password' --base64-output=auto --database='limit output to this database' -vv mysql-bin.number | less
</syntaxhighlight> if you get
ERROR: Failed on connect: SSL connection error: protocol version mismatch
try <source lang=bash>
- mysqlbinlog --read-from-remote-server --host='your replication host' --user='your replication user' --password='your replication password' --ssl-mode=DISABLED --base64-output=auto --database='limit output to this database' -vv mysql-bin.number | less
</syntaxhighlight>
For an idea of the binlog file to investigate on the master do this on your slave: <source lang=bash>
- mysql -e 'show slave status\G' | awk '$1=="Master_Log_File:"'
</syntaxhighlight>
Filesystems for MySQL
ext3/ext4
Create Options
<source lang=bash>
- mkfs.ext4 -b 4096 /dev/mapper/vg--data-lv--ext4--mysql_data
</syntaxhighlight>
Mountoptions
- noatime
- data=writeback (best performance , only metadata is logged)
- data=ordered (ok performance , recording metadata and grouping metadata related to the data changes)
- data=journal (worst performance, but best data protection, ext3 default mode, recording metadata and all data)
Raw devices with InnoDB
Take a look at setting device permissions via udev first.
After that the device is owned by mysql: <source lang=bash>
- ls -alL /dev/vg-data/lv-rawdisk-innodb01
brw-rw---- 1 mysql mysql 252, 0 Aug 12 15:07 /dev/vg-data/lv-rawdisk-innodb01 </syntaxhighlight>
Determine the size: <source lang=bash>
- lvs vg-data
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert lv-rawdisk-innodb01 vg-data -wi-a---- 25.00g
- fdisk -l /dev/vg-data/lv-rawdisk-innodb01
Disk /dev/vg-data/lv-rawdisk-innodb01: 26.8 GB, 26843545600 bytes 255 heads, 63 sectors/track, 3263 cylinders, total 52428800 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000
- bc -l
26843545600/(1024*1024*1024) 25.00000000000000000000 </syntaxhighlight> Yes... really 25GB!
Add your logical volume to your configuration /etc/mysql/conf.d/innodb.cnf : <source lang=mysql> [mysqld]
- InnoDB raw disks
innodb_data_home_dir= innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Gnewraw </syntaxhighlight>
Start mysql: <source lang=bash>
- service mysql start
</syntaxhighlight>
Aaaaaand.. do not forget apparmor! Like I did.. :-D <source lang=mysql> InnoDB: Operating system error number 13 in a file operation. InnoDB: The error means mysqld does not have the access rights to InnoDB: the directory. InnoDB: File name /dev/dm-0 InnoDB: File operation call: 'open'. InnoDB: Cannot continue operation. </syntaxhighlight>
<source lang=bash>
- tail /var/log/kern.log
... Aug 12 15:30:09 mysql kernel: [ 5840.118528] audit: type=1400 audit(1439386209.399:33): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/dev/dm-0" pid=11810 comm="mysqld" requested_mask="wr" denied_mask="wr" fsuid=108 ouid=108 ... </syntaxhighlight> Add your raw device to the apparmor config in /etc/apparmor.d/local/usr.sbin.mysqld : <source lang=bash>
- Site-specific additions and overrides for usr.sbin.mysqld.
- For more details, please see /etc/apparmor.d/local/README.
/dev/dm-* rwk, </syntaxhighlight>
Reload apparmor: <source lang=bash>
- service apparmor reload
</syntaxhighlight>
Another try! <source lang=bash>
- service mysql start
</syntaxhighlight>
<source lang=mysql> InnoDB: The first specified data file /dev/vg-data/lv-rawdisk-innodb01 did not exist: InnoDB: a new database to be created! 150812 15:48:23 InnoDB: Setting file /dev/vg-data/lv-rawdisk-innodb01 size to 25600 MB InnoDB: Database physically writes the file full: wait... InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 1100 1200 ... </syntaxhighlight>
Much better!
So shutdown MySQL again!
Change your configuration /etc/mysql/conf.d/innodb.cnf and change newraw to raw! : <source lang=mysql> [mysqld]
- InnoDB raw disks
innodb_data_home_dir= innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Graw </syntaxhighlight>
NFS
NFSv4
On NetApp CDOT SVM
<source lang=text> cdot1nfsv4::> export-policy rule create -policyname default -clientmatch 172.18.128.0/22 -superuser none -rwrule none -rorule sys -allow-dev false -allow-suid false cdot1nfsv4::> cdot1nfsv4::> export-policy create -policyname mysql_clients cdot1nfsv4::> export-policy rule create -policyname mysql_clients -clientmatch 172.18.128.0/22 -superuser sys -rwrule sys -rorule sys -allow-dev true -allow-suid false cdot1nfsv4::> cdot1nfsv4::> nfs server modify -v4.0 enabled -v4-id-domain this.domain.tld cdot1nfsv4::> set -units GB cdot1nfsv4::> vol show -volume MYSQLNFS_* -fields volume,policy,size,junction-path vserver volume size policy junction-path
--------------------- ---- ------------- ----------------------
cdot1nfsv4 MYSQLNFS_DATA 40GB mysql_clients /MYSQLNFS_DATA cdot1nfsv4 MYSQLNFS_LOG 1GB mysql_clients /MYSQLNFS_LOG 2 entries were displayed. </syntaxhighlight>
Links:
- How to configure NFSv4 in Cluster-Mode
- Clustered Data ONTAP NFS Expert recommended articles
- How to configure NetApp storage systems for Network File System version 4 in AIX and Linux environments
- How to enable or disable NFSv4 on NetApp storage systems
On Linux
Blacklist rpcsec_gss_krb5
To disable loading of the rpcsec_gss_krb5 kernel module which causes problems with performance, do this: <source lang=text>
- echo "blacklist rpcsec_gss_krb5" > /etc/modprobe.d/blacklist-rpcsec_gss_krb5.conf
- rmmod rpcsec_gss_krb5
</syntaxhighlight>
/etc/sysctl.d/99-mysql.conf
<source lang=text>
-
- Semaphores & IPC for optimizations in innodb
kernel.shmmax=2147483648 kernel.shmall=2147483648 kernel.msgmni=1024 kernel.msgmax=65536 kernel.sem=250 32000 32 1024
- Swap
vm.swappiness = 0 vm.vfs_cache_pressure = 50 </syntaxhighlight>
/etc/sysctl.d/99-netapp-nfs.conf
<source lang=text>
-
- Optimization for netapp/nfs increased from 64k, @see http://tldp.org/HOWTO/NFS-HOWTO/performance.html#MEMLIMITS
net.core.wmem_default=262144 net.core.rmem_default=262144 net.core.wmem_max=262144 net.core.rmem_max=262144
net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.ipv4.tcp_no_metrics_save = 1
- Guidelines from http://media.netapp.com/documents/mysqlperformance-5.pdf
net.ipv4.tcp_sack=0 net.ipv4.tcp_timestamps=0 sunrpc.tcp_slot_table_entries=128
- nfs.v3.enable on
nfs.tcp.enable=on nfs.tcp.recvwindowsize=65536 nfs.tcp.xfersize=65536
- iscsi.iswt.max_ios_per_session 128
- iscsi.iswt.tcp_window_size 131400
- iscsi.max_connections_per_session 16
net.ipv4.tcp_tw_reuse = 1 net.ipv4.ip_local_port_range = 1024 65023 net.ipv4.tcp_max_syn_backlog = 10240 net.ipv4.tcp_max_tw_buckets = 400000 net.ipv4.tcp_max_orphans = 60000 net.ipv4.tcp_synack_retries = 3 net.core.somaxconn = 10000
kernel.sysrq=0
net.ipv4.neigh.default.gc_thresh1 = 4096 net.ipv4.neigh.default.gc_thresh2 = 8192 net.ipv4.neigh.default.gc_thresh3 = 8192 net.ipv4.neigh.default.base_reachable_time = 86400 net.ipv4.neigh.default.gc_stale_time = 86400 </syntaxhighlight>
Raise allowed number of open files for mysql in /etc/security/limits.d/mysql.conf
<source lang=text> mysql soft nofile 1024000 mysql hard nofile 1024000 mysql soft nproc 10240 mysql hard nproc 10240 </syntaxhighlight>
Modify systemd mysql.service to raise the number of files limit
To raise the number of files for the service you have to tell the systemd the new limit.
<source lang=bash>
- systemctl edit mysql.service
</syntaxhighlight> and enter: <source lang=ini> [Service]
LimitNOFILE=1024000
</syntaxhighlight> <source lang=bash>
- systemctl cat mysql
- /lib/systemd/system/mysql.service
- MySQL systemd service file
...
- /etc/systemd/system/mysql.service.d/override.conf
[Service]
LimitNOFILE=1024000
</syntaxhighlight>
Do not forget to activate and check the limit <source lang=bash>
- systemctl daemon-reload
- systemctl restart mysql
- awk 'NR==1 || /Max open files/' /proc/$(pgrep mysqld$)/limits
Limit Soft Limit Hard Limit Units Max open files 1024000 1024000 files </syntaxhighlight>
Modify systemd service to wait for NFS
To be sure that the NFS mount is ready when the mysql server starts add After=nfs-client.target to the systemd service in the Unit-section. <source lang=bash>
- systemctl edit mysql.service
</syntaxhighlight> and enter: <source lang=ini> [Unit]
Description=MySQL Community Server After=network.target After=nfs-client.target
</syntaxhighlight>
<source lang=bash>
- systemctl cat mysql
- /lib/systemd/system/mysql.service
- MySQL systemd service file
[Unit] Description=MySQL Community Server After=network.target
[Install] WantedBy=multi-user.target
[Service] User=mysql Group=mysql PermissionsStartOnly=true ExecStartPre=/usr/share/mysql/mysql-systemd-start pre ExecStart=/usr/sbin/mysqld ExecStartPost=/usr/share/mysql/mysql-systemd-start post TimeoutSec=600 Restart=on-failure RuntimeDirectory=mysqld RuntimeDirectoryMode=755
- /etc/systemd/system/mysql.service.d/override.conf
[Unit]
Description=MySQL Community Server After=network.target After=nfs-client.target
[Service]
LimitNOFILE=1024000
</syntaxhighlight>
Do not forget to activate the changes... <source lang=bash>
- systemctl daemon-reload
- systemctl restart mysql
</syntaxhighlight>
... and check they are active: <source lang=bash>
- systemctl list-dependencies --after mysql.service | grep nfs-client.target
● ├─nfs-client.target </syntaxhighlight>
/etc/idmapd.conf
<source lang=text>
- Domain = localdomain
Domain = this.domain.tld </syntaxhighlight>
/etc/fstab
<source lang=text> cdot-nfsv4-svm:/MYSQLNFS_LOG /MYSQLNFS_LOG nfs rw,hard,nointr,rsize=65536,wsize=65536,bg,vers=4,proto=tcp,noatime cdot-nfsv4-svm:/MYSQLNFS_DATA /MYSQLNFS_DATA nfs rw,hard,nointr,rsize=65536,wsize=65536,bg,vers=4,proto=tcp,noatime </syntaxhighlight>
/etc/mysql/mysql.conf.d/mysqld.cnf
<source lang=ini> [mysqld] ... datadir = /MYSQLNFS_DATA/data/mysql ... </syntaxhighlight>
/etc/mysql/mysql.conf.d/innodb.cnf
<source lang=ini> [mysqld]
- * InnoDB
innodb_data_home_dir = /MYSQLNFS_DATA/InnoDB innodb_data_file_path = ibdata1:200M:autoextend innodb_log_group_home_dir = /MYSQLNFS_LOG/ib_log
- innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 2 innodb_file_per_table = on </syntaxhighlight> <source lang=mysql>
- mysql -e "show variables where variable_name like '%dir' and value like '/MYSQLNFS%'"
+---------------------------+------------------------------------+ | Variable_name | Value | +---------------------------+------------------------------------+ | datadir | /MYSQLNFS_DATA/data/mysql/ | | innodb_data_home_dir | /MYSQLNFS_DATA/InnoDB | | innodb_log_group_home_dir | /MYSQLNFS_LOG/ib_log | +---------------------------+------------------------------------+ </syntaxhighlight>
/etc/mysql/mysql.conf.d/query_cache.cnf
<source lang=ini> [mysqld]
- * Query Cache Configuration
query_cache_type = 1 query_cache_limit = 256K query_cache_min_res_unit = 2k query_cache_size = 80M </syntaxhighlight>
<source lang=mysql> mysql> SHOW VARIABLES LIKE 'have_query_cache'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | have_query_cache | YES | +------------------+-------+ 1 row in set (0,00 sec)
mysql> SHOW VARIABLES LIKE 'query_cache%'; +------------------------------+----------+ | Variable_name | Value | +------------------------------+----------+ | query_cache_limit | 262144 | | query_cache_min_res_unit | 2048 | | query_cache_size | 83886080 | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | +------------------------------+----------+ 5 rows in set (0,00 sec) </syntaxhighlight>
apparmor : /etc/apparmor.d/local/usr.sbin.mysqld
<source lang=text>
- vim:syntax=apparmor
- This should be always there...
owner @{PROC}/@{pid}/status r, /sys/devices/system/node/ r, /sys/devices/system/node/** r,
- The mysql datadir, innodb_data_home_dir
/MYSQLNFS_DATA/ r, /MYSQLNFS_DATA/** rwk,
- The mysql innodb_log_group_home_dir
/MYSQLNFS_LOG/ r, /MYSQLNFS_LOG/** rwk,
</syntaxhighlight>
Short stupid performance test
<source lang=bash>
- time dd if=/dev/zero of=/MYSQLNFS_DATA/io.test bs=16k count=65536
65536+0 records in 65536+0 records out 1073741824 bytes (1,1 GB, 1,0 GiB) copied, 1,7552 s, 612 MB/s
real 0m1.772s user 0m0.016s sys 0m0.672s </syntaxhighlight> Some things seem to work...
Sample InnoDB configuration
/etc/mysql/conf.d/innodb.cnf <source lang=mysql> [mysqld]
- InnoDB Parameters
- innodb_buffer_pool_size=(0.7*total_mem_size)
innodb_buffer_pool_size=1433M
- bulk_insert_buffer_size
bulk_insert_buffer_size=256M
- innodb_buffer_pool_instances=... more = more concurrency
innodb_buffer_pool_instances=2
- innodb_thread_concurrency= 2*CPUs
innodb_thread_concurrency=4
- innodb_flush_method=O_DIRECT (avoids double buffering)
innodb_flush_method=O_DIRECT
- InnoDB data raw disks
innodb_data_home_dir= innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Graw
- InnoDB log files
innodb_log_files_in_group=2 innodb_log_file_size=100M innodb_log_group_home_dir=/var/lib/mysql/ib_log </syntaxhighlight>
Analyze
<source lang=mysql> mysql> select * from <tablename> PROCEDURE ANALYSE(); </syntaxhighlight>
<source lang=mysql> mysql> SHOW /*!50000 GLOBAL*/ STATUS; </syntaxhighlight>
- See [MySQL Performance Tuning]
Find statements which lead into an error
<source lang=mysql> mysql> select CURRENT_SCHEMA,DIGEST_TEXT,MYSQL_ERRNO,MESSAGE_TEXT from performance_schema.events_statements_history where errors!=0\G
- 1. row ***************************
CURRENT_SCHEMA: NULL
DIGEST_TEXT: NULL MYSQL_ERRNO: 1046 MESSAGE_TEXT: No database selected
1 row in set (0,00 sec) </syntaxhighlight>
percona-toolkit
<source lang=bash>
- aptitude install percona-toolkit
- mysql -e "explain select * from mysql.user,mysql.db where user.user=db.user" | pt-visual-explain
JOIN +- Bookmark lookup | +- Table | | table db | | possible_keys User | +- Index lookup | key db->User | possible_keys User | key_len 48 | ref mysql.user.User | rows 3 +- Table scan
rows 68 +- Table table user
</syntaxhighlight>
Sysbench
<source lang=bash>
- mysql -u root -e "create database sbtest;"
- sysbench \
--test=oltp \ --oltp-table-size=10000000 \ --db-driver=mysql \ --mysql-table-engine=innodb \ --mysql-db=sbtest \ --mysql-user=root \ --mysql-password=$(nawk -F'=' '/password/{print $2}' /root/.my.cnf) \ --mysql-socket=/var/run/mysqld/mysqld.sock \ prepare
- sysbench \
--test=oltp \ --oltp-test-mode=complex \ --oltp-table-size=80000000 \ --db-driver=mysql \ --mysql-table-engine=innodb \ --mysql-db=sbtest \ --mysql-user=root \ --mysql-password=$(nawk -F'=' '/password/{print $2}' /root/.my.cnf) \ --mysql-socket=/var/run/mysqld/mysqld.sock \ --num-threads=4 \ --max-time=900 \ --max-requests=500000 \ run
- mysql -u root_rw -e "drop table sbtest;" sbtest
</syntaxhighlight>
Recover a damaged root account
Lost grants
Try out: <source lang=bash>
- service mysql stop
- echo "grant all privileges on *.* to 'root'@'localhost' with grant option;" > /root/mysql-init
- mysqld_safe --init-file=/root/mysql-init
... 150812 19:14:24 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
- rm /root/mysql-init
- service mysql start
</syntaxhighlight> Or: <source lang=bash>
- service mysql stop
- mysqld_safe --skip-grant-tables &
...
- mysql -e "UPDATE mysql.user SET Grant_priv='Y', Super_priv='Y' WHERE User='root'; FLUSH PRIVILEGES; GRANT ALL ON *.* TO 'root'@'localhost';"
- mysqladmin -u root shutdown
- service mysql start
</syntaxhighlight>
Lost password
<source lang=bash>
- service mysql stop
- echo "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('the root password for mysql');" > /root/mysql-init
- mysqld_safe --init-file=/root/mysql-init
... 150812 19:15:24 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
- rm /root/mysql-init
- service mysql start
</syntaxhighlight>
Structured configuration
This is the default in Ubuntus /etc/mysql/my.cnf: <source lang=mysql> ...
- * IMPORTANT: Additional settings that can override those from this file!
- The files must end with '.cnf', otherwise they'll be ignored.
!includedir /etc/mysql/conf.d/ </syntaxhighlight>
/etc/mysql/conf.d/innodb.cnf: <source lang=mysql> [mysqld]
- InnoDB Parameters
- innodb_buffer_pool_size=(0.7*total_mem_size)
- innodb_buffer_pool_size=512M
innodb_buffer_pool_size=256M
- bulk_insert_buffer_size
- bulk_insert_buffer_size=256M
bulk_insert_buffer_size=128M
- innodb_buffer_pool_instances=... more = more concurrency
innodb_buffer_pool_instances=2
- innodb_thread_concurrency= 2*CPUs
innodb_thread_concurrency=4
- innodb_flush_method=O_DIRECT (avoids double buffering)
innodb_flush_method=O_DIRECT
- InnoDB data raw disks
innodb_data_home_dir= innodb_data_file_path=/dev/vg-data/lv-rawdisk-innodb01:25Graw
- InnoDB log files
innodb_log_files_in_group=2 innodb_log_file_size=100M innodb_log_group_home_dir=/var/lib/mysql/ib_log </syntaxhighlight>
/etc/mysql/conf.d/myisam.cnf: <source lang=mysql> [mysqld]
- key_buffer = 512M
key_buffer = 128M table_cache = 8K myisam_sort_buffer_size = 64M tmp_table_size = 64M
- Variable: concurrent_insert
- Value Description
- 0 Disables concurrent inserts
- 1 (Default) Enables concurrent insert for MyISAM tables that do not have holes
- 2 Enables concurrent inserts for all MyISAM tables, even those that have holes.
- For a table with a hole, new rows are inserted at the end of the table if it is in use by another thread.
- Otherwise, MySQL acquires a normal write lock and inserts the row into the hole.
concurrent_insert=2
- Variable: myisam_use_mmap
- https://www.percona.com/blog/2006/05/26/myisam-mmap-feature-51/
myisam_use_mmap=1 </syntaxhighlight>
/etc/mysql/conf.d/mysqld.cnf: <source lang=mysql> [mysqld] datadir = /var/lib/mysql/data/data
- because mysql is soooo stupid
- ignore-db-dirs = lost+found # when we will have mysql >= 5.6.3
bind-address = 127.0.0.1
open-files-limit = 4096 max_connections = 512
max_allowed_packet = 16M thread_stack = 192K thread_cache_size = 8 myisam-recover-options = BACKUP max_connections = 512 table_cache = 8192 thread_concurrency = 4
default-storage-engine = innodb
- Enable the full query log. Every query (even ones with incorrect
- syntax) that the server receives will be logged. This is useful for
- debugging, it is usually disabled in production use.
- log
- Print warnings to the error log file. If you have any problem with
- MySQL you should enable logging of warnings and examine the error log
- for possible explanations.
log_warnings
- Log slow queries. Slow queries are queries which take more than the
- amount of time defined in "long_query_time" or which do not use
- indexes well, if log_long_format is enabled. It is normally good idea
- to have this turned on if you frequently add new queries to the
- system.
log_slow_queries slow_query_log_file = /var/log/mysql/mysql-slow.log
- All queries taking more than this amount of time (in seconds) will be
- trated as slow. Do not use "1" as a value here, as this will result in
- even very fast queries being logged from time to time (as MySQL
- currently measures time with second accuracy only).
long_query_time = 2
- Log more information in the slow query log. Normally it is good to
- have this turned on. This will enable logging of queries that are not
- using indexes in addition to long running queries.
- log_long_format
log_bin = /var/lib/mysql/binlog/mysql-bin.log expire_logs_days = 10 max_binlog_size = 100M sync_binlog = 0
performance_schema = ON </syntaxhighlight>
/etc/mysql/conf.d/mysqld_safe.cnf: <source lang=mysql> [mysqld_safe] </syntaxhighlight>
/etc/mysql/conf.d/mysqld_safe_syslog.cnf: <source lang=mysql> [mysqld_safe] syslog </syntaxhighlight>
/etc/mysql/conf.d/query_cache.cnf: <source lang=mysql> [mysqld] query_cache_limit = 4M query_cache_size = 128M query_cache_min_res_unit = 2K </syntaxhighlight>
MySQL Clients
Small one liners for testing purposes.
PHP
PHP PDO
<source lang=php> $ php -r '
$pdo=new PDO("mysql:host=mydbhost;dbname=mydb", "user", "pass", ARRAY( PDO::ATTR_PERSISTENT => true ) ); $stmt=$pdo->prepare("SELECT * FROM mytable"); if($stmt->execute()){ while($row = $stmt->fetch()){ print_r($row); } }; $stmt = null; $pdo=null;
' </syntaxhighlight>