參考:https://blog.csdn.net/wudinaniya/article/details/81094578
1、首先去mysql官網下載rpm包,一個是server包一個是client包。官網下載地址:https://www.mysql.com/downloads/
這里用mysql community server里邊的。這里使用的是5.7.x版本了,不使用Mysql8.x版本了。
我這里使用的是Centos7.x版本的64位操作系統,使用mysql5.7版本的數據庫。查看linux操作系統版本和系統內核版本,如下所示:
1 [root@k8s-node3 ~]# cat /etc/redhat-release # 查看操作系統版本 2 CentOS Linux release 7.6.1810 (Core) 3 [root@k8s-node3 ~]# uname -r # 檢查系統內核版本 4 3.10.0-957.el7.x86_64 5 [root@k8s-node3 ~]#
選擇對應的Linux版本和x86/x64進行下載,可以選擇 RPM Bundle,下載完記得解壓 tar -xvf xxx.tar。
可以離線下載上傳或者在線下載包,如下所示:
1 [root@k8s-node3 package]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el7.x86_64.rpm-bundle.tar 2 --2020-07-15 13:46:49-- https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el7.x86_64.rpm-bundle.tar 3 Resolving downloads.mysql.com (downloads.mysql.com)... 137.254.60.14 4 Connecting to downloads.mysql.com (downloads.mysql.com)|137.254.60.14|:443... failed: Connection refused. 5 [root@k8s-node3 package]# wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.22-1.el7.x86_64.rpm-bundle.tar 6 --2020-07-15 13:47:14-- https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.22-1.el7.x86_64.rpm-bundle.tar 7 Resolving dev.mysql.com (dev.mysql.com)... 137.254.60.11 8 Connecting to dev.mysql.com (dev.mysql.com)|137.254.60.11|:443... connected. 9 HTTP request sent, awaiting response... 302 Found 10 Location: https://cdn.mysql.com//archives/mysql-5.7/mysql-5.7.22-1.el7.x86_64.rpm-bundle.tar [following] 11 --2020-07-15 13:47:16-- https://cdn.mysql.com//archives/mysql-5.7/mysql-5.7.22-1.el7.x86_64.rpm-bundle.tar 12 Resolving cdn.mysql.com (cdn.mysql.com)... 104.85.161.42 13 Connecting to cdn.mysql.com (cdn.mysql.com)|104.85.161.42|:443... connected. 14 HTTP request sent, awaiting response... 200 OK 15 Length: 598026240 (570M) [application/x-tar] 16 Saving to: ‘mysql-5.7.22-1.el7.x86_64.rpm-bundle.tar’ 17 18 20% [=================> ] 125,263,632 2.17MB/s eta 4m 55s
也可以細化下載,下載須要的mysql組件,有4個:分別是 server、client、common、libs。
卸載舊版本的MySql,如果沒有的話,則跳過即可,直接安裝mysql。
1 [root@k8s-node3 package]# rpm -qa | grep mysql 2 [root@k8s-node3 package]#
如果有的話,將會列出舊版本MySql的組件列表,逐個刪除掉舊的組件,使用命令rpm -e --nodeps {-file-name}進行移除操作,移除的時候可能會有依賴,要注意一定的順序,{-file-name}是待刪除的mysql的文件。我這里是沒有,直接略過了。
2、使用 rpm 命令方式安裝mysql組件,使用命令rpm -ivh {-file-name}進行安裝操作。按照依賴關系依次安裝rpm包 依賴關系依次common→libs→client→server。如下所示:
備注:在ivh中, i-install安裝、v-verbose進度條、h-hash哈希校驗。
1 [root@k8s-node3 package]# rpm -ivh mysql-community-common-5.7.30-1.el7.x86_64.rpm 2 warning: mysql-community-common-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 3 Preparing... ################################# [100%] 4 file /usr/share/mysql/czech/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 5 file /usr/share/mysql/danish/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 6 file /usr/share/mysql/dutch/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 7 file /usr/share/mysql/english/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 8 file /usr/share/mysql/estonian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 9 file /usr/share/mysql/french/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 10 file /usr/share/mysql/german/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 11 file /usr/share/mysql/greek/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 12 file /usr/share/mysql/hungarian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 13 file /usr/share/mysql/italian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 14 file /usr/share/mysql/japanese/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 15 file /usr/share/mysql/korean/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 16 file /usr/share/mysql/norwegian-ny/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 17 file /usr/share/mysql/norwegian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 18 file /usr/share/mysql/polish/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 19 file /usr/share/mysql/portuguese/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 20 file /usr/share/mysql/romanian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 21 file /usr/share/mysql/russian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 22 file /usr/share/mysql/serbian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 23 file /usr/share/mysql/slovak/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 24 file /usr/share/mysql/spanish/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 25 file /usr/share/mysql/swedish/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 26 file /usr/share/mysql/ukrainian/errmsg.sys from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 27 file /usr/share/mysql/charsets/Index.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 28 file /usr/share/mysql/charsets/armscii8.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 29 file /usr/share/mysql/charsets/ascii.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 30 file /usr/share/mysql/charsets/cp1250.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 31 file /usr/share/mysql/charsets/cp1251.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 32 file /usr/share/mysql/charsets/cp1256.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 33 file /usr/share/mysql/charsets/cp1257.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 34 file /usr/share/mysql/charsets/cp850.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 35 file /usr/share/mysql/charsets/cp852.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 36 file /usr/share/mysql/charsets/cp866.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 37 file /usr/share/mysql/charsets/dec8.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 38 file /usr/share/mysql/charsets/geostd8.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 39 file /usr/share/mysql/charsets/greek.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 40 file /usr/share/mysql/charsets/hebrew.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 41 file /usr/share/mysql/charsets/hp8.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 42 file /usr/share/mysql/charsets/keybcs2.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 43 file /usr/share/mysql/charsets/koi8r.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 44 file /usr/share/mysql/charsets/koi8u.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 45 file /usr/share/mysql/charsets/latin1.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 46 file /usr/share/mysql/charsets/latin2.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 47 file /usr/share/mysql/charsets/latin5.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 48 file /usr/share/mysql/charsets/latin7.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 49 file /usr/share/mysql/charsets/macce.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 50 file /usr/share/mysql/charsets/macroman.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 51 file /usr/share/mysql/charsets/swe7.xml from install of mysql-community-common-5.7.30-1.el7.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64 52 [root@k8s-node3 package]# rpm -ivh mysql-community-libs-5.7.30-1.el7.x86_64.rpm 53 warning: mysql-community-libs-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 54 error: Failed dependencies: 55 mysql-community-common(x86-64) >= 5.7.9 is needed by mysql-community-libs-5.7.30-1.el7.x86_64 56 mariadb-libs is obsoleted by mysql-community-libs-5.7.30-1.el7.x86_64 57 [root@k8s-node3 package]# rpm -ivh mysql-community-server-5.7.30-1.el7.x86_64.rpm 58 warning: mysql-community-server-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 59 error: Failed dependencies: 60 mysql-community-client(x86-64) >= 5.7.9 is needed by mysql-community-server-5.7.30-1.el7.x86_64 61 mysql-community-common(x86-64) = 5.7.30-1.el7 is needed by mysql-community-server-5.7.30-1.el7.x86_64 62 [root@k8s-node3 package]# rpm -ivh mysql-community-client-5.7.30-1.el7.x86_64.rpm 63 warning: mysql-community-client-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 64 error: Failed dependencies: 65 mysql-community-libs(x86-64) >= 5.7.9 is needed by mysql-community-client-5.7.30-1.el7.x86_64 66 [root@k8s-node3 package]#
在安裝 mysql-community-libs-5.7.30-1.el7.x86_64.rpm 時有可能會報錯,這個是mysql依賴錯誤,解決方法是:清除yum里所有mysql依賴包。
1 [root@k8s-node3 package]# rpm -qa|grep mysql 2 [root@k8s-node3 package]# yum remove mysql-libs 3 Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager 4 5 This system is not registered with an entitlement server. You can use subscription-manager to register. 6 7 Resolving Dependencies 8 --> Running transaction check 9 ---> Package mariadb-libs.x86_64 1:5.5.60-1.el7_5 will be erased 10 --> Processing Dependency: libmysqlclient.so.18()(64bit) for package: 2:postfix-2.10.1-7.el7.x86_64 11 --> Processing Dependency: libmysqlclient.so.18(libmysqlclient_18)(64bit) for package: 2:postfix-2.10.1-7.el7.x86_64 12 --> Running transaction check 13 ---> Package postfix.x86_64 2:2.10.1-7.el7 will be erased 14 --> Processing Dependency: /usr/sbin/sendmail for package: redhat-lsb-core-4.1-27.el7.centos.1.x86_64 15 --> Restarting Dependency Resolution with new changes. 16 --> Running transaction check 17 ---> Package redhat-lsb-core.x86_64 0:4.1-27.el7.centos.1 will be erased 18 --> Finished Dependency Resolution 19 base/7/x86_64 | 3.6 kB 00:00:00 20 centos-gluster7/7/x86_64 | 3.0 kB 00:00:00 21 extras/7/x86_64 | 2.9 kB 00:00:00 22 extras/7/x86_64/primary_db | 205 kB 00:00:00 23 updates/7/x86_64 | 2.9 kB 00:00:00 24 updates/7/x86_64/primary_db | 3.0 MB 00:00:00 25 26 Dependencies Resolved 27 28 ================================================================================================================================ 29 Package Arch Version Repository Size 30 ================================================================================================================================ 31 Removing: 32 mariadb-libs x86_64 1:5.5.60-1.el7_5 @anaconda 4.4 M 33 Removing for dependencies: 34 postfix x86_64 2:2.10.1-7.el7 @anaconda 12 M 35 redhat-lsb-core x86_64 4.1-27.el7.centos.1 @base 45 k 36 37 Transaction Summary 38 ================================================================================================================================ 39 Remove 1 Package (+2 Dependent packages) 40 41 Installed size: 17 M 42 Is this ok [y/N]: y 43 Downloading packages: 44 Running transaction check 45 Running transaction test 46 Transaction test succeeded 47 Running transaction 48 Erasing : redhat-lsb-core-4.1-27.el7.centos.1.x86_64 1/3 49 Erasing : 2:postfix-2.10.1-7.el7.x86_64 2/3 50 Erasing : 1:mariadb-libs-5.5.60-1.el7_5.x86_64 3/3 51 Verifying : redhat-lsb-core-4.1-27.el7.centos.1.x86_64 1/3 52 Verifying : 2:postfix-2.10.1-7.el7.x86_64 2/3 53 Verifying : 1:mariadb-libs-5.5.60-1.el7_5.x86_64 3/3 54 55 Removed: 56 mariadb-libs.x86_64 1:5.5.60-1.el7_5 57 58 Dependency Removed: 59 postfix.x86_64 2:2.10.1-7.el7 redhat-lsb-core.x86_64 0:4.1-27.el7.centos.1 60 61 Complete! 62 [root@k8s-node3 package]#
注意:有的系統可能不太一樣,沒有mysql-libs,而是mariadb-libs,此時要移除的則是mariadb-libs。
1 [root@k8s-node3 package]# rpm -qa|grep mariadb 2 [root@k8s-node3 package]# yum remove mariadb-libs
清除完yum里所有mysql的依賴包后,再次安裝mysql組件就不會報錯了,如下所示:
1 [root@k8s-node3 package]# rpm -ivh mysql-community-common-5.7.30-1.el7.x86_64.rpm 2 warning: mysql-community-common-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 3 Preparing... ################################# [100%] 4 Updating / installing... 5 1:mysql-community-common-5.7.30-1.e################################# [100%] 6 [root@k8s-node3 package]# rpm -ivh mysql-community-libs-5.7.30-1.el7.x86_64.rpm 7 warning: mysql-community-libs-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 8 Preparing... ################################# [100%] 9 Updating / installing... 10 1:mysql-community-libs-5.7.30-1.el7################################# [100%] 11 [root@k8s-node3 package]# rpm -ivh mysql-community-server-5.7.30-1.el7.x86_64.rpm 12 warning: mysql-community-server-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 13 error: Failed dependencies: 14 mysql-community-client(x86-64) >= 5.7.9 is needed by mysql-community-server-5.7.30-1.el7.x86_64 15 [root@k8s-node3 package]# rpm -ivh mysql-community-client-5.7.30-1.el7.x86_64.rpm 16 warning: mysql-community-client-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 17 Preparing... ################################# [100%] 18 Updating / installing... 19 1:mysql-community-client-5.7.30-1.e################################# [100%] 20 [root@k8s-node3 package]#
我這里server安裝失敗了,我這里強制安裝,先安裝一下,如下所示:
1 [root@k8s-node3 package]# ls 2 mysql-5.7.22-1.el7.x86_64.rpm-bundle.tar mysql-community-libs-5.7.30-1.el7.x86_64.rpm 3 mysql-community-client-5.7.30-1.el7.x86_64.rpm mysql-community-server-5.7.30-1.el7.x86_64.rpm 4 mysql-community-common-5.7.30-1.el7.x86_64.rpm 5 [root@k8s-node3 package]# rpm -ivh mysql-community-server-5.7.30-1.el7.x86_64.rpm --nodeps --force 6 warning: mysql-community-server-5.7.30-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 7 Preparing... ################################# [100%] 8 Updating / installing... 9 1:mysql-community-server-5.7.30-1.e################################# [100%] 10 [root@k8s-node3 package]#
注意:執行 yum remove mysql-libs命令后,會自動刪除掉 /etc/ 下的 my.cnf 文件,對於安裝mysql組件,只有安裝了 mysql-community-server-5.7.30-1.el7.x86_64.rpm 組件,才會在 /etc/下生成 my.cnf 文件 和 my.cnf.d 文件夾。
1 [root@k8s-node3 package]# ls /etc/my.cnf 2 /etc/my.cnf 3 [root@k8s-node3 package]# ls /etc/my.cnf.d/ 4 [root@k8s-node3 package]# ls /etc/my* 5 /etc/my.cnf 6 7 /etc/my.cnf.d: 8 [root@k8s-node3 package]#
在/var/lib/下可以看到以下三個文件夾mysql、mysql-files、mysql-keyring,如下所示:
1 [root@k8s-node3 package]# cd /var/lib/ 2 [root@k8s-node3 lib]# ls 3 AccountsService color flatpak glusterd lldpad mysql-keyring polkit-1 rpm-state tpm yum 4 alsa colord fprint gssproxy logrotate net-snmp postfix rsyslog tuned 5 alternatives containers fwupd hyperv machines NetworkManager pulse samba udisks2 6 authconfig dbus fwupdate initramfs misc nfs rasdaemon selinux unbound 7 bluetooth dhclient games iscsi mlocate os-prober rhsm setroubleshoot upower 8 boltd dnsmasq gdm kubelet mysql PackageKit rpcbind stateless vmware 9 chrony docker geoclue libvirt mysql-files plymouth rpm systemd xkb 10 [root@k8s-node3 lib]# ls mysql mysql- 11 mysql-files/ mysql-keyring/ 12 [root@k8s-node3 lib]# ls mysql mysql- 13 mysql-files/ mysql-keyring/ 14 [root@k8s-node3 lib]# ls mysql mysql-files/ mysql-keyring/ 15 mysql: 16 17 mysql-files/: 18 19 mysql-keyring/: 20 [root@k8s-node3 lib]#
在/var/log/ 下可以看到 mysqld.log 文件,如下所示:
1 [root@k8s-node3 lib]# cd /var/lo 2 local/ lock/ log/ 3 [root@k8s-node3 lib]# cd /var/log/ 4 [root@k8s-node3 log]# ls 5 anaconda cron libvirt qemu-ga spooler-20200714 vmware-vgauthsvc.log.0 6 audit cron-20200618 maillog rhsm swtpm vmware-vmsvc.log 7 boot.log cron-20200625 maillog-20200618 sa tallylog vmware-vmusr.log 8 boot.log-20200618 cron-20200628 maillog-20200625 samba tuned wpa_supplicant.log 9 boot.log-20200622 cron-20200714 maillog-20200628 secure vmware-network.1.log wtmp 10 boot.log-20200629 cups maillog-20200714 secure-20200618 vmware-network.2.log Xorg.0.log 11 boot.log-20200630 dmesg messages secure-20200625 vmware-network.3.log Xorg.0.log.old 12 boot.log-20200702 dmesg.old messages-20200618 secure-20200628 vmware-network.4.log Xorg.9.log 13 boot.log-20200703 firewalld messages-20200625 secure-20200714 vmware-network.5.log yum.log 14 boot.log-20200714 gdm messages-20200628 speech-dispatcher vmware-network.6.log 15 btmp gitlab messages-20200714 spooler vmware-network.7.log 16 btmp-20200702 glusterfs mysqld.log spooler-20200618 vmware-network.8.log 17 chrony grubby_prune_debug pluto spooler-20200625 vmware-network.9.log 18 containers lastlog ppp spooler-20200628 vmware-network.log 19 [root@k8s-node3 log]# ll mysqld.log 20 -rw-r----- 1 mysql mysql 0 Jul 15 14:17 mysqld.log 21 [root@k8s-node3 log]#
在/var/run/ 下可以看到 mysqld 目錄,如下所示:
1 [root@k8s-node3 log]# cd /var/run/ 2 [root@k8s-node3 run]# ls 3 abrt cups gitlab lock NetworkManager setrans udev 4 alsactl.pid dbus gluster log plymouth setroubleshoot udisks2 5 atd.pid dmeventd-client glusterd.pid lsm ppp sm-notify.pid user 6 auditd.pid dmeventd-server glusterd.socket lvm radvd spice-vdagentd utmp 7 avahi-daemon docker gssproxy.pid lvmetad.pid rhsm sshd.pid vmware 8 blkid docker.pid gssproxy.sock mcelog-client rpcbind sudo xtables.lock 9 console docker.sock initramfs mcelog.pid rpcbind.lock sysconfig 10 container-storage-setup ebtables.lock ksmtune.pid mdadm rpcbind.sock syslogd.pid 11 crond.pid faillock kubernetes mount runc systemd 12 cron.reboot flannel libvirt mysqld samba tmpfiles.d 13 cryptsetup gdm libvirtd.pid netreport sepermit tuned 14 [root@k8s-node3 run]# ls mysqld/ 15 [root@k8s-node3 run]# ll mysqld/ 16 total 0 17 [root@k8s-node3 run]#
3、登錄並創建 mysql 密碼,啟動mysql,安裝完后,使用命令 service mysqld start 或 systemctl start mysqld.service 啟動MySQL服務,如果mysql服務無法啟動,就重啟一下系統。
1 [root@k8s-node3 ~]# systemctl start mysqld.service 2 [root@k8s-node3 ~]# systemctl status mysqld.service 3 ● mysqld.service - MySQL Server 4 Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) 5 Active: active (running) since Wed 2020-07-15 14:23:18 CST; 11s ago 6 Docs: man:mysqld(8) 7 http://dev.mysql.com/doc/refman/en/using-systemd.html 8 Process: 129166 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=exited, status=0/SUCCESS) 9 Process: 129095 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS) 10 Main PID: 129169 (mysqld) 11 Tasks: 27 12 Memory: 259.3M 13 CGroup: /system.slice/mysqld.service 14 └─129169 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid 15 16 Jul 15 14:23:12 k8s-node3 systemd[1]: Starting MySQL Server... 17 Jul 15 14:23:18 k8s-node3 systemd[1]: Started MySQL Server. 18 [root@k8s-node3 ~]#
啟動、停止、查看狀態命令如下所示:
1 systemctl start mysqld.service # 此命令是啟動mysql 2 systemctl status mysqld.service # 此命令是查看mysql狀態 3 systemctl stop mysqld.service # 此命令是關閉mysql
查看mysql進程 ps -ef | grep mysql,查看3306端口 netstat -anop | grep 3306。
1 [root@k8s-node3 ~]# ps -ef | grep mysql 2 mysql 129169 1 0 14:23 ? 00:00:00 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid 3 root 129514 121741 0 14:25 pts/2 00:00:00 grep --color=auto mysql 4 [root@k8s-node3 ~]# netstat -nultp | grep 3306 5 tcp6 0 0 :::3306 :::* LISTEN 129169/mysqld 6 [root@k8s-node3 ~]#
登陸mysql修改root密碼,由於MySQL5.7.4之前的版本中默認是沒有密碼的,登錄后直接回車就可以進入數據庫,進而進行設置密碼等操作。其后版本對密碼等安全相關操作進行了一些改變,在安裝過程中,會在安裝日志中生成一個臨時密碼。使用命令grep 'temporary password' /var/log/mysqld.log找到這個臨時密碼。
1 [root@k8s-node3 ~]# grep 'temporary password' /var/log/mysqld.log 2 2020-07-15T06:23:15.406927Z 1 [Note] A temporary password is generated for root@localhost: OUvw#frSq7iI 3 [root@k8s-node3 ~]#
即可查詢到類似於如下的一條日志記錄,如下所示:
1 [root@k8s-node3 ~]# grep 'temporary password' /var/log/mysqld.log 2 2020-07-15T06:23:15.406927Z 1 [Note] A temporary password is generated for root@localhost: OUvw#frSq7iI 3 [root@k8s-node3 ~]#
OUvw#frSq7iI即為登錄密碼。使用這個隨機密碼登錄進去,然后修改密碼,如下所示:
1 [root@k8s-node3 ~]# grep 'temporary password' /var/log/mysqld.log 2 2020-07-15T06:23:15.406927Z 1 [Note] A temporary password is generated for root@localhost: OUvw#frSq7iI 3 [root@k8s-node3 ~]# mysql -uroot -p 4 Enter password: 5 Welcome to the MySQL monitor. Commands end with ; or \g. 6 Your MySQL connection id is 2 7 Server version: 5.7.30 8 9 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 10 11 Oracle is a registered trademark of Oracle Corporation and/or its 12 affiliates. Other names may be trademarks of their respective 13 owners. 14 15 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 16 17 mysql> set password for root@localhost=password('123456'); 18 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements 19 mysql> set global validate_password_policy=0; # 此時,新密碼長度大於等於8位才有效,否則報錯 20 Query OK, 0 rows affected (0.00 sec) 21 22 mysql> set global validate_password_length=1; # 修改有效密碼長度。 23 Query OK, 0 rows affected (0.00 sec) 24 25 mysql> set password for root@localhost=password('123456'); 26 Query OK, 0 rows affected, 1 warning (0.01 sec) 27 28 mysql>
執行下面的命令set password for root@localhost=password('123456');修改MySql root密碼,但是在5.6后,mysql內置密碼增強機制,低強度密碼會報錯:ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。
1 第一步是,更改策略,設置 validate_password_policy=0; 2 mysql> set global validate_password_policy=0; # 此時,新密碼長度大於等於8位才有效,否則報錯 3 4 然后修改有效密碼長度: 5 mysql> set global validate_password_length=1; 6 不管設置 validate_password_length=1,還是2,3,4 ,"使密碼長度生效"這個參數的實際值都是4。超過4后設置是多少實際就是多少。 7 8 第二步就可以重新設置密碼了,如下所示: 9 mysql> set password for root@localhost=password('123456'); 10 Query OK, 0 rows affected, 1 warning (0.01 sec)
使用修改之后的密碼就可以順利登錄,如下所示:
1 [root@k8s-node3 ~]# mysql -uroot -p123456 2 mysql: [Warning] Using a password on the command line interface can be insecure. 3 Welcome to the MySQL monitor. Commands end with ; or \g. 4 Your MySQL connection id is 3 5 Server version: 5.7.30 MySQL Community Server (GPL) 6 7 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 8 9 Oracle is a registered trademark of Oracle Corporation and/or its 10 affiliates. Other names may be trademarks of their respective 11 owners. 12 13 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 14 15 mysql>
此時,雖然防火牆我時關着的,但root用戶只能用於本機訪問,不能用於遠程訪問,否則會報以下錯誤。因此,接下來要做的是授予root用戶遠程訪問權限。
查看當前授予過的權限,如下所示:
1 [root@k8s-node3 ~]# mysql -uroot -p123456 2 mysql: [Warning] Using a password on the command line interface can be insecure. 3 Welcome to the MySQL monitor. Commands end with ; or \g. 4 Your MySQL connection id is 3 5 Server version: 5.7.30 MySQL Community Server (GPL) 6 7 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 8 9 Oracle is a registered trademark of Oracle Corporation and/or its 10 affiliates. Other names may be trademarks of their respective 11 owners. 12 13 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 14 15 mysql> use mysql; 16 Reading table information for completion of table and column names 17 You can turn off this feature to get a quicker startup with -A 18 19 Database changed 20 mysql> select user,host from user; 21 +---------------+-----------+ 22 | user | host | 23 +---------------+-----------+ 24 | mysql.session | localhost | 25 | mysql.sys | localhost | 26 | root | localhost | 27 +---------------+-----------+ 28 3 rows in set (0.00 sec) 29 30 mysql> grant all privileges on *.* to root@'%' identified by '123456'; # 授予root用戶遠程訪問權限。 31 Query OK, 0 rows affected, 1 warning (0.00 sec) 32 33 mysql> flush privileges; # 刷新權限,使設置生效。 34 Query OK, 0 rows affected (0.00 sec) 35 36 mysql>
現在可以遠程鏈接服務器上面的mysql數據庫,如下所示:
4、驗證mysql安裝成功,如下所示:
1 [root@k8s-node3 ~]# mysqladmin --version 2 mysqladmin Ver 8.42 Distrib 5.7.30, for Linux on x86_64 3 [root@k8s-node3 ~]#
查看mysql檢查是否開機自啟動,服務前面存在*的是開機自啟動的,沒有*的是開機不自啟動的,如下所示:
1 [root@k8s-node3 ~]# ntsysv 2 3 ntsysv 1.7.4 - (C) 2000-2001 Red Hat, Inc. 4 5 6 ─┐ 7 │ 8 What services should be automatically started? │ 9 │ 10 [*] mdmonitor.service ↑ │ 11 [*] microcode.service ? │ 12 [*] multipathd.service ? │ 13 [*] mysqld.service ? │ 14 [ ] ndctl-monitor.service ? │ 15 [ ] netcf-transaction.service ? │ 16 [ ] nfs-blkmap.service ? │ 17 [ ] nfs-rquotad.service ? │ 18 [ ] nfs-server.service ? │ 19 [ ] nfs.service ↓ │ 20 │ 21 ┌────┐ ┌────────┐ │ 22 │ Ok │ │ Cancel │ │ 23 └────┘ └────────┘ │ 24 │ 25 │ │ 26 └──────────────────────────────────────────────────┘ 27 28 29 Press <F1> for more information on a service.
mysql的核心目錄,如下所示:
1 1)、/var/lib/mysql,mysql的安裝目錄。 2 2)、/usr/share/mysql/,mysql的配置文件。 3 3)、/usr/bin/,mysql的命令目錄。 4 5 6 [root@k8s-node3 ~]# ls /var/lib/mysql 7 auto.cnf client-cert.pem ibdata1 ibtmp1 mysql.sock.lock public_key.pem sys 8 ca-key.pem client-key.pem ib_logfile0 mysql performance_schema server-cert.pem 9 ca.pem ib_buffer_pool ib_logfile1 mysql.sock private_key.pem server-key.pem 10 [root@k8s-node3 ~]# ls /usr/share/mysql/ 11 bulgarian french mysql-log-rotate romanian 12 charsets german mysql_security_commands.sql russian 13 czech greek mysql_sys_schema.sql serbian 14 danish hungarian mysql_system_tables_data.sql slovak 15 dictionary.txt innodb_memcached_config.sql mysql_system_tables.sql spanish 16 dutch install_rewriter.sql mysql_test_data_timezone.sql swedish 17 english italian norwegian ukrainian 18 errmsg-utf8.txt japanese norwegian-ny uninstall_rewriter.sql 19 estonian korean polish 20 fill_help_tables.sql magic portuguese 21 [root@k8s-node3 ~]# ls /usr/bin/
5、查看Mysql的字符集編碼,如下所示:
1 [root@k8s-node3 ~]# mysql -uroot -p123456 2 mysql: [Warning] Using a password on the command line interface can be insecure. 3 Welcome to the MySQL monitor. Commands end with ; or \g. 4 Your MySQL connection id is 4 5 Server version: 5.7.30 MySQL Community Server (GPL) 6 7 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 8 9 Oracle is a registered trademark of Oracle Corporation and/or its 10 affiliates. Other names may be trademarks of their respective 11 owners. 12 13 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 14 15 mysql> show variables like '%char%'; 16 +--------------------------------------+----------------------------+ 17 | Variable_name | Value | 18 +--------------------------------------+----------------------------+ 19 | character_set_client | utf8 | 20 | character_set_connection | utf8 | 21 | character_set_database | latin1 | 22 | character_set_filesystem | binary | 23 | character_set_results | utf8 | 24 | character_set_server | latin1 | 25 | character_set_system | utf8 | 26 | character_sets_dir | /usr/share/mysql/charsets/ | 27 | validate_password_special_char_count | 1 | 28 +--------------------------------------+----------------------------+ 29 9 rows in set (0.00 sec) 30 31 mysql>
設置字符集編碼為utf8格式的,如下所示:
1 # For advice on how to change settings please see 2 # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html 3 4 [mysqld] 5 init_connect='SET NAMES utf8' 6 character-set-server=utf8 7 # character_set_client=utf8 8 collation-server=utf8_general_ci 9 # 10 # Remove leading # and set to the amount of RAM for the most important data 11 # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. 12 # innodb_buffer_pool_size = 128M 13 # 14 # Remove leading # to turn on a very important data integrity option: logging 15 # changes to the binary log between backups. 16 # log_bin 17 # 18 # Remove leading # to set options mainly useful for reporting servers. 19 # The server defaults are faster for transactions and fast SELECTs. 20 # Adjust sizes as needed, experiment to find the optimal values. 21 # join_buffer_size = 128M 22 # sort_buffer_size = 2M 23 # read_rnd_buffer_size = 2M 24 datadir=/var/lib/mysql 25 socket=/var/lib/mysql/mysql.sock 26 27 # Disabling symbolic-links is recommended to prevent assorted security risks 28 symbolic-links=0 29 30 log-error=/var/log/mysqld.log 31 pid-file=/var/run/mysqld/mysqld.pid 32 33 [mysql] 34 default-character-set=utf8 35 36 [mysql_safe] 37 default-character-set=utf8 38 "my.cnf" 41L, 1192C
修改內容,如下所示:
此時,需要重啟mysql的,如下所示:
1 [root@k8s-node3 etc]# systemctl restart mysqld.service 2 [root@k8s-node3 etc]# systemctl status mysqld.service 3 ● mysqld.service - MySQL Server 4 Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) 5 Active: active (running) since Wed 2020-07-15 18:49:25 CST; 2s ago 6 Docs: man:mysqld(8) 7 http://dev.mysql.com/doc/refman/en/using-systemd.html 8 Process: 26346 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=exited, status=0/SUCCESS) 9 Process: 26322 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS) 10 Main PID: 26349 (mysqld) 11 Tasks: 27 12 Memory: 218.8M 13 CGroup: /system.slice/mysqld.service 14 └─26349 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid 15 16 Jul 15 18:49:23 k8s-node3 systemd[1]: Starting MySQL Server... 17 Jul 15 18:49:25 k8s-node3 systemd[1]: Started MySQL Server.
再次查看字符集編碼,如下所示:
1 mysql> SHOW VARIABLES LIKE 'character_set_%'; 2 +--------------------------+----------------------------+ 3 | Variable_name | Value | 4 +--------------------------+----------------------------+ 5 | character_set_client | utf8 | 6 | character_set_connection | utf8 | 7 | character_set_database | utf8 | 8 | character_set_filesystem | binary | 9 | character_set_results | utf8 | 10 | character_set_server | utf8 | 11 | character_set_system | utf8 | 12 | character_sets_dir | /usr/share/mysql/charsets/ | 13 +--------------------------+----------------------------+ 14 8 rows in set (0.01 sec) 15 16 mysql> SHOW VARIABLES LIKE 'collation_%'; 17 +----------------------+-----------------+ 18 | Variable_name | Value | 19 +----------------------+-----------------+ 20 | collation_connection | utf8_general_ci | 21 | collation_database | utf8_general_ci | 22 | collation_server | utf8_general_ci | 23 +----------------------+-----------------+ 24 3 rows in set (0.01 sec) 25 26 mysql>
注意,修改字符集編碼,只對后面創建的數據庫生效,之前創建的數據庫字符集還是保持之前的不發生變化。
6、Mysql的命令行清屏命令system clear或者ctrl + L命令,如下所示:
1 mysql> system clear 2 mysql>
mysql的邏輯分層,分別是連接層、服務層、引擎層、存儲層,如下所示:
查看mysql的存儲引擎,首先查看mysql支持的引擎,如下所示:
1 [root@k8s-node3 ~]# mysql -uroot -p123456 2 mysql: [Warning] Using a password on the command line interface can be insecure. 3 Welcome to the MySQL monitor. Commands end with ; or \g. 4 Your MySQL connection id is 5 5 Server version: 5.7.30 MySQL Community Server (GPL) 6 7 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 8 9 Oracle is a registered trademark of Oracle Corporation and/or its 10 affiliates. Other names may be trademarks of their respective 11 owners. 12 13 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 14 15 mysql> show engines; 16 +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 17 | Engine | Support | Comment | Transactions | XA | Savepoints | 18 +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 19 | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | 20 | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | 21 | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | 22 | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | 23 | MyISAM | YES | MyISAM storage engine | NO | NO | NO | 24 | CSV | YES | CSV storage engine | NO | NO | NO | 25 | ARCHIVE | YES | Archive storage engine | NO | NO | NO | 26 | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | 27 | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | 28 +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 29 9 rows in set (0.01 sec) 30 31 mysql>
查看當前Mysql的存儲引擎,如下所示:
1 mysql> show variables like '%storage_engine%'; 2 +----------------------------------+--------+ 3 | Variable_name | Value | 4 +----------------------------------+--------+ 5 | default_storage_engine | InnoDB | 6 | default_tmp_storage_engine | InnoDB | 7 | disabled_storage_engines | | 8 | internal_tmp_disk_storage_engine | InnoDB | 9 +----------------------------------+--------+ 10 4 rows in set (0.00 sec) 11 12 mysql>
查看某個數據表使用了什么存儲引擎,在顯示結果里參數engine后面的就表示該表當前用的存儲引擎。
1 mysql> show create table user_info; 2 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 3 | Table | Create Table | 4 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 5 | user_info | CREATE TABLE `user_info` ( 6 `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶編號', 7 `user_account` varchar(15) DEFAULT NULL COMMENT '用戶賬號', 8 `user_pw` varchar(15) DEFAULT NULL COMMENT '用戶密碼', 9 `user_number` varchar(15) DEFAULT NULL COMMENT '用戶手機號', 10 `user_name` varchar(10) DEFAULT NULL COMMENT '用戶姓名', 11 `user_age` int(11) DEFAULT NULL COMMENT '用戶年齡', 12 `user_sex` varchar(5) DEFAULT NULL COMMENT '用戶性別', 13 `user_mark` varchar(5) DEFAULT NULL COMMENT '用戶標志', 14 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '用戶創建時間', 15 `is_sync` int(3) DEFAULT '0' COMMENT '用戶標識', 16 `is_money` varchar(255) DEFAULT NULL COMMENT '是否繳納押金', 17 PRIMARY KEY (`user_id`) USING BTREE, 18 KEY `user_id` (`user_id`) USING BTREE 19 ) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='用戶信息表' | 20 +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 21 1 row in set (0.00 sec) 22 23 mysql>
7、mysql的sql優化,原因可能是性能低,執行時間太長,等待時間太長,sql語句欠佳,比如連接查詢,索引失效,服務器參數設置不佳。
Sql的編寫過程、解析過程,如下所示:
1 編寫過程:select distinct ... from ... join ... on ... where ... group by ... having ... order by ... limit ... 2 解析過程:from ... on ... join ... where ... group by ... having ... select distinct ... order by ... limit ...
SQL優化,主要就是在於優化索引,索引相當於是書的目錄。索引,index是幫助Mysql高效獲取數據的數據結構,索引是數據結構(樹,常見的B樹,默認是B樹,Hash樹)。
索引的弊端,索引本身很大,可以存放在內存或者硬盤中,通常為硬盤。索引不是所有情況均適用的,如果是少量數據不適用。如果是頻繁更新的字段不適用。很少使用的列也不適合添加索引。索引會降低增刪改的效率,提高查詢的效率。
索引的優點,提高查詢效率,降低IO使用率,降低CPU使用率,因為B樹索引本事就是一個排好序的結構,因此在排序的時候,可以直接使用的。
8、mysql如何進行優化呢,查看使用索引的情況,查詢執行計划,explain + SQL語句。
1 mysql> explain select * from book_info; 2 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+ 3 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+ 5 | 1 | SIMPLE | book_info | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 100.00 | NULL | 6 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+ 7 1 row in set, 1 warning (0.01 sec)
詳細信息介紹,如下所示:
1 id :編號 2 select_type :查詢類型 3 table :數據表,指的查詢的那張表。 4 partitions : 5 type :類型 6 possible_keys : 預測使用到的索引 7 key :實際使用的索引 8 key_len : 實際使用索引的長度 9 ref : 表之間的引用 10 rows : 通過索引查詢到的數據量 11 filtered : 12 Extra :額外的信息
8.1、id編號的用法,多表關聯查詢(備注:多表聯查都可以轉換為子查詢得到想要的結果)特點:
1)、id編號值相同,數據小的表,優先查詢。
2)、如果是id編號值不同,id編號值越大越優先查詢(執行本質,在嵌套子查詢的時候,先查詢內層,再查詢外層)。
3)、id值有相同,又有不同,id值越大越優先。id值相同從上往下,順序執行。這里的id編號指定的是explain的查詢結果字段id哦。
1 mysql> explain 2 -> select * from book_info bi,book_sort bs WHERE bi.book_sort_id = bs.book_sort_id and bi.book_name = 'Java'; 3 +----+-------------+-------+------------+--------+------------------------+-----------+---------+----------------------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+--------+------------------------+-----------+---------+----------------------+------+----------+-------------+ 6 | 1 | SIMPLE | bi | NULL | ref | book_sort_id,book_name | book_name | 48 | const | 1 | 100.00 | Using where | 7 | 1 | SIMPLE | bs | NULL | eq_ref | PRIMARY | PRIMARY | 4 | book.bi.book_sort_id | 1 | 100.00 | NULL | 8 +----+-------------+-------+------------+--------+------------------------+-----------+---------+----------------------+------+----------+-------------+ 9 2 rows in set, 1 warning (0.00 sec) 10 11 mysql>
1 mysql> explain 2 -> select * from book_info bi WHERE bi.book_sort_id = (SELECT book_sort_id from book_sort bs WHERE bs.book_sort_name = '自然科學總論') 3 -> ; 4 +----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------------+ 5 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 6 +----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------------+ 7 | 1 | PRIMARY | bi | NULL | ref | book_sort_id | book_sort_id | 5 | const | 2 | 100.00 | Using where | 8 | 2 | SUBQUERY | bs | NULL | ALL | NULL | NULL | NULL | NULL | 21 | 10.00 | Using where | 9 +----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------------+ 10 2 rows in set, 1 warning (0.00 sec) 11 12 mysql>
8.2)、select_type查詢類型的用法,如下所示:
1)、PRIMARY:包含子查詢SQL中的主查詢,一般是SQL嵌套的最外層。
2)、SUBQUERY:包含子查詢SQL中的子查詢,一般是SQL嵌套的非最外層。
3)、SIMPLE:簡單查詢,不包含子查詢,不包含union查詢。
4)、DERIVED:衍生查詢。在查詢的時候使用到了臨時表。兩種情況,第一種是from子查詢中只有一張表。第二種是在from子查詢中,如果有兩張表table1 union table2連接查詢,則table1這個左表就是衍生查詢。
1 mysql> explain 2 -> SELECT b.book_name from (SELECT * from book_info WHERE book_name in ('Java') UNION SELECT * from book_info WHERE book_name in ('python') ) b; 3 +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ 6 | 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL | 7 | 2 | DERIVED | book_info | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 10.00 | Using where | 8 | 3 | UNION | book_info | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 10.00 | Using where | 9 | NULL | UNION RESULT | <union2,3> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary | 10 +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ 11 4 rows in set, 1 warning (0.00 sec) 12 13 mysql>
DERIVED代表了衍生表,table的值是derived2代表了是主查詢涉及到衍生表,而2代表了指明了id編號是2,代表了衍生了那張表,臨時表是從id為2的這個table是book_info來的。
8.3)、type成為索引類型,或者稱為類型。system > const > eq_ref > ref > index > all,其中性能由左向右依次降低,但是system、const只是理想狀態,實際可以達到的一般是ref、range。
1)、system,只有一條數據的系統表,基本達不到,或者衍生表只有一條數據的主查詢,偶爾可以達到。
2)、const,僅僅可以查詢到一條數據的sql,並且用於Primary key或者unique索引的時候就是const。必須針對Primary key或者unique索引的時候,與索引類型有關。
3)、eq_ref,唯一性索引,對於每個索引鍵的查詢,返回匹配唯一行數據,唯一的意思是有且只有一個,不能多也不能為0。常見於唯一索引和主鍵索引。
4)、ref,非唯一性索引,對於每個索引鍵的查詢,返回匹配的所有行(可以是0個或者多個)。
5)、range,檢索指定范圍的行,具體就是where后面是一個范圍查詢,比如between and、in、>、<等等。特殊的in有時候會失效,從而轉換為無索引All,即in范圍查詢會導致索引失效,可以將in范圍查詢放到字段查詢的后面。
6)、index,查詢全部索引的數據。只需要掃描索引表,不需要掃描全部數據。
7)、all,查詢全部表中數據。需要掃描全表,即需要所有表中的所有數據。
1 mysql> explain select * from book_info where book_id > 5; 2 +----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 3 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4 +----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 5 | 1 | SIMPLE | book_info | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 13 | 100.00 | Using where | 6 +----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 7 1 row in set, 1 warning (0.00 sec)
8.4)、possible_keys,可能用到的索引,是一種預測,不准。
8.5)、key,實際使用到的索引。如果possible_keys或者key為NULL,說明沒有使用到索引。
1 mysql> explain select * from book_info where book_id > 5; 2 +----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 3 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4 +----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 5 | 1 | SIMPLE | book_info | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 13 | 100.00 | Using where | 6 +----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+ 7 1 row in set, 1 warning (0.00 sec)
8.6)、key_len,索引的長度。作用就是用於判斷復合索引是否被完全使用。
1)、utf8中,一個字符占用三個字節。如果索引字段可以為null,則會使用1個字節用於標識。如果是固定長度char就是char(n)中的n乘以三,如果可以為null,再加一即可。
2)、utf8中,一個字符占用三個字節。如果索引字段可以為null,則會使用1個字節用於標識。如果是可變長度varchar,就是varchar(n)中的n乘以三,如果可以為null,再加一,然后varhar是可變長度,然后再加二,用兩個字節來表示可變長度。比如book_name是varchar(15),15 * 3 + 1 + 2 = 48。如果是復合索引,book_type是varchar(200),組合book_name是varchar(15),就是200 * 3 + 1 + 2 + 15 * 3 + 1 + 2 = 651。
1 mysql> EXPLAIN 2 -> SELECT * from book_info WHERE book_name = 'Java' and book_type = '自然科學總論'; 3 +----+-------------+-----------+------------+------+-----------------------------------------+-----------+---------+-------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+------+-----------------------------------------+-----------+---------+-------+------+----------+-------------+ 6 | 1 | SIMPLE | book_info | NULL | ref | book_type,book_name,book_name_book_type | book_name | 48 | const | 1 | 12.50 | Using where | 7 +----+-------------+-----------+------------+------+-----------------------------------------+-----------+---------+-------+------+----------+-------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql> EXPLAIN 11 -> SELECT * from book_info WHERE book_name = 'Java' and book_type = '自然科學總論'; 12 +----+-------------+-----------+------------+------+-------------------------------+---------------------+---------+-------------+------+----------+-------+ 13 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 14 +----+-------------+-----------+------------+------+-------------------------------+---------------------+---------+-------------+------+----------+-------+ 15 | 1 | SIMPLE | book_info | NULL | ref | book_type,book_name_book_type | book_name_book_type | 651 | const,const | 1 | 100.00 | NULL | 16 +----+-------------+-----------+------------+------+-------------------------------+---------------------+---------+-------------+------+----------+-------+ 17 1 row in set, 1 warning (0.00 sec) 18 19 mysql>
注意:utf8是一個字符三個節點,gbk是一個字符兩個字節,latin是一個字符一個字節。
8.7)、ref,注意與type中的ref值進行區分,作用是指明當前表所參照的字段。如果是常量,值就是const。
1 mysql> EXPLAIN 2 -> SELECT bi.* from book_info bi,book_sort bs WHERE bi.book_sort_id = bs.book_sort_id and bi.book_name = 'Java'; 3 +----+-------------+-------+------------+--------+----------------------------------+---------------------+---------+----------------------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+--------+----------------------------------+---------------------+---------+----------------------+------+----------+-------------+ 6 | 1 | SIMPLE | bi | NULL | ref | book_sort_id,book_name_book_type | book_name_book_type | 48 | const | 1 | 100.00 | Using where | 7 | 1 | SIMPLE | bs | NULL | eq_ref | PRIMARY | PRIMARY | 4 | book.bi.book_sort_id | 1 | 100.00 | Using index | 8 +----+-------------+-------+------------+--------+----------------------------------+---------------------+---------+----------------------+------+----------+-------------+ 9 2 rows in set, 1 warning (0.00 sec) 10 11 mysql>
8.8)、rows,被索引優化查詢的數據個數。
1 mysql> EXPLAIN 2 -> SELECT bi.* from book_info bi,book_sort bs WHERE bi.book_sort_id = bs.book_sort_id and bi.book_name = 'Java'; 3 +----+-------------+-------+------------+--------+----------------------------------+---------------------+---------+----------------------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+--------+----------------------------------+---------------------+---------+----------------------+------+----------+-------------+ 6 | 1 | SIMPLE | bi | NULL | ref | book_sort_id,book_name_book_type | book_name_book_type | 48 | const | 1 | 100.00 | Using where | 7 | 1 | SIMPLE | bs | NULL | eq_ref | PRIMARY | PRIMARY | 4 | book.bi.book_sort_id | 1 | 100.00 | Using index | 8 +----+-------------+-------+------------+--------+----------------------------------+---------------------+---------+----------------------+------+----------+-------------+ 9 2 rows in set, 1 warning (0.00 sec)
8.9)、Extra,就是額外的,剩下的意思,常見的有using filesort(出現這種情況要避免)、Using temporary(出現這種情況要避免)、Using where、Using index。
1)、using filesort:表示性能低,消耗比較大,當前的sql語句需要額外的一次排序查詢。理解起來就是先根據這個字段查詢,然后根據這個字段排序。如果是先根據一個字段查詢,根據另外一個字段排序,那么當前的sql語句需要額外的一次排序查詢。常見於order by語句中。
1 mysql> SELECT * from book_info WHERE book_name = 'Java' ORDER BY book_name; 2 +---------+--------------+-----------+-------------+------------+--------------------+-----------------+----------+-----------+---------------------+------------+-------------------------------------+ 3 | book_id | book_sort_id | book_name | book_author | book_price | book_type | book_publish | book_sum | book_mark | create_time | book_money | book_desc | 4 +---------+--------------+-----------+-------------+------------+--------------------+-----------------+----------+-----------+---------------------+------------+-------------------------------------+ 5 | 3 | 19 | Java | 別先生 | 29.90 | 自然科學總論 | 科學出版社 | 6 | NULL | 2019-02-15 19:09:45 | 199.00 | <p>Java大神如何練成的?</p> | 6 +---------+--------------+-----------+-------------+------------+--------------------+-----------------+----------+-----------+---------------------+------------+-------------------------------------+ 7 1 row in set (0.00 sec) 8 9 mysql> EXPLAIN 10 -> SELECT * from book_info WHERE book_name = 'Java' ORDER BY book_author; 11 +----+-------------+-----------+------------+------+---------------------+---------------------+---------+-------+------+----------+---------------------------------------+ 12 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 13 +----+-------------+-----------+------------+------+---------------------+---------------------+---------+-------+------+----------+---------------------------------------+ 14 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_type | book_name_book_type | 48 | const | 1 | 100.00 | Using index condition; Using filesort | 15 +----+-------------+-----------+------------+------+---------------------+---------------------+---------+-------+------+----------+---------------------------------------+ 16 1 row in set, 1 warning (0.00 sec) 17 18 mysql>
總結:對於單索引,如果排序和查找是同一字段,則不會出現using filesort,如果排序和查找不是同一字段,則會出現using filesort。
對於復合索引,不能跨列(最佳左前綴,即從左到右依次使用,不能跨列使用,比如三個字段的索引,不能跨過第二個索引)。where和order by按照復合索引的順序使用,不要跨列或者無序使用。
1 mysql> EXPLAIN 2 -> SELECT * from book_info WHERE book_name = 'Java' ORDER BY book_author; 3 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+---------------------------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+---------------------------------------+ 6 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_type_book_author | book_name_book_type_book_author | 48 | const | 1 | 100.00 | Using index condition; Using filesort | 7 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+---------------------------------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql> EXPLAIN 11 -> SELECT * from book_info WHERE book_name = 'Java' ORDER BY book_type; 12 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-----------------------+ 13 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 14 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-----------------------+ 15 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_type_book_author | book_name_book_type_book_author | 48 | const | 1 | 100.00 | Using index condition | 16 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-----------------------+ 17 1 row in set, 1 warning (0.00 sec) 18 19 mysql>
2)、Using temporary:性能損耗大,用到了臨時表。一般出現在group by的語句中。如何避免?查詢那些列,就根據那些列進行group by進行分組。出現的原因就是已經有表了,但是不使用,必須再來一張臨時表進行分組查詢出結果。
1 mysql> EXPLAIN 2 -> SELECT book_name from book_info WHERE book_name = 'Java' GROUP BY book_name; 3 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-------------+ 6 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_type_book_author | book_name_book_type_book_author | 48 | const | 1 | 100.00 | Using index | 7 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql> EXPLAIN 11 -> SELECT book_name from book_info WHERE book_name = 'Java' GROUP BY book_publish; 12 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+--------------------------------------------------------+ 13 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 14 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+--------------------------------------------------------+ 15 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_type_book_author | book_name_book_type_book_author | 48 | const | 1 | 100.00 | Using index condition; Using temporary; Using filesort | 16 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+--------------------------------------------------------+ 17 1 row in set, 1 warning (0.00 sec) 18 19 mysql>
重點,解析過程:from ... on ... join ... where ... group by ... having ... select distinct ... order by ... limit ...
3)、Using index:表示性能提升了,意思是索引覆蓋,原因在於不讀取原文件,只從索引文件中獲取數據,不需要回表查詢。只要使用到的列全部都在索引中,就是索引覆蓋Using index。只要使用到的列不都在索引中,就不會出現索引覆蓋Using index。
1 mysql> EXPLAIN 2 -> SELECT book_name from book_info WHERE book_name = 'Java'; 3 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-------------+ 6 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_type_book_author | book_name_book_type_book_author | 48 | const | 1 | 100.00 | Using index | 7 +----+-------------+-----------+------------+------+---------------------------------+---------------------------------+---------+-------+------+----------+-------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql> EXPLAIN 11 -> SELECT book_name from book_info WHERE book_name = 'Java' or book_type = '自然科學總論'; 12 +----+-------------+-----------+------------+-------+-------------------------------------------+---------------------------------+---------+------+------+----------+--------------------------+ 13 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 14 +----+-------------+-----------+------------+-------+-------------------------------------------+---------------------------------+---------+------+------+----------+--------------------------+ 15 | 1 | SIMPLE | book_info | NULL | index | book_type,book_name_book_type_book_author | book_name_book_type_book_author | 699 | NULL | 16 | 19.00 | Using where; Using index | 16 +----+-------------+-----------+------------+-------+-------------------------------------------+---------------------------------+---------+------+------+----------+--------------------------+ 17 1 row in set, 1 warning (0.00 sec) 18 19 mysql> EXPLAIN 20 -> SELECT book_name from book_info WHERE book_type = '自然科學總論' or book_name = 'Java' ; 21 +----+-------------+-----------+------------+-------+-------------------------------------------+---------------------------------+---------+------+------+----------+--------------------------+ 22 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 23 +----+-------------+-----------+------------+-------+-------------------------------------------+---------------------------------+---------+------+------+----------+--------------------------+ 24 | 1 | SIMPLE | book_info | NULL | index | book_type,book_name_book_type_book_author | book_name_book_type_book_author | 699 | NULL | 16 | 19.00 | Using where; Using index | 25 +----+-------------+-----------+------------+-------+-------------------------------------------+---------------------------------+---------+------+------+----------+--------------------------+ 26 1 row in set, 1 warning (0.00 sec) 27 28 mysql>
如果用到了索引覆蓋,索引覆蓋Using index會對possible_keys、key造成影響,如果沒有where,則索引只出現在key中,如果有where,則索引出現在key和possible_keys中。
1 mysql> EXPLAIN SELECT book_name from book_info; 2 +----+-------------+-----------+------------+-------+---------------+-----------------------+---------+------+------+----------+-------------+ 3 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4 +----+-------------+-----------+------------+-------+---------------+-----------------------+---------+------+------+----------+-------------+ 5 | 1 | SIMPLE | book_info | NULL | index | NULL | book_name_book_author | 96 | NULL | 16 | 100.00 | Using index | 6 +----+-------------+-----------+------------+-------+---------------+-----------------------+---------+------+------+----------+-------------+ 7 1 row in set, 1 warning (0.00 sec) 8 9 10 mysql> EXPLAIN SELECT book_name from book_info WHERE book_name = '自然科學總論'; 11 +----+-------------+-----------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------------+ 12 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 13 +----+-------------+-----------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------------+ 14 | 1 | SIMPLE | book_info | NULL | ref | book_name_book_author | book_name_book_author | 48 | const | 1 | 100.00 | Using index | 15 +----+-------------+-----------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------------+ 16 1 row in set, 1 warning (0.00 sec) 17 18 mysql>
4)、Using where:表示需要從原表中查詢。即需要回表查詢的。
1 mysql> EXPLAIN 2 -> SELECT book_name,book_type from book_info WHERE book_type = 'Java' ; 3 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 6 | 1 | SIMPLE | book_info | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 10.00 | Using where | 7 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 8 1 row in set, 1 warning (0.01 sec) 9 10 mysql>
5)、impossibal where,where子句永遠為false。
1 mysql> EXPLAIN 2 -> SELECT book_name,book_type from book_info WHERE book_type = 'Java' AND book_type = 'Python' ; 3 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ 6 | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE | 7 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+ 8 1 row in set, 1 warning (0.01 sec) 9 10 mysql>
條件字段的順序最好和組合索引的順序一致,如果不一致,SQL優化器可以會對sql進行優化,使用到索引,但是強烈推薦保持條件字段順序和組合索引順序一致。如果復合索引和使用的順序一致(且不跨列使用),則復合索引全部使用,如果部分一致,則使用部分索引。
9、mysql的單表索引優化案例,如下所示:
1 SET NAMES utf8mb4; 2 SET FOREIGN_KEY_CHECKS = 0; 3 4 -- ---------------------------- 5 -- Table structure for user_info 6 -- ---------------------------- 7 DROP TABLE IF EXISTS `user_info`; 8 CREATE TABLE `user_info` ( 9 `user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶編號', 10 `user_account` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶賬號', 11 `user_pw` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶密碼', 12 `user_number` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶手機號', 13 `user_name` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶姓名', 14 `user_age` int(11) DEFAULT NULL COMMENT '用戶年齡', 15 `user_sex` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶性別', 16 `user_mark` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶標志', 17 `create_time` datetime(0) DEFAULT CURRENT_TIMESTAMP COMMENT '用戶創建時間', 18 `is_sync` int(3) DEFAULT 0 COMMENT '用戶標識', 19 `is_money` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '是否繳納押金', 20 PRIMARY KEY (`user_id`) USING BTREE 21 ) ENGINE = InnoDB AUTO_INCREMENT = 42 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用戶信息表' ROW_FORMAT = Dynamic; 22 23 SET FOREIGN_KEY_CHECKS = 1;
索引一旦進行升級優化,需要將之前廢棄的索引刪除掉,防止干擾。
首先進行需求查詢,如下所示:
1 mysql> EXPLAIN 2 -> SELECT user_account from user_info WHERE user_age in (22,33) and user_name = '小別同志' ORDER BY user_age 3 -> ; 4 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+ 5 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 6 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+ 7 | 1 | SIMPLE | user_info | NULL | ALL | NULL | NULL | NULL | NULL | 21 | 4.76 | Using where; Using filesort | 8 +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+ 9 1 row in set, 1 warning (0.00 sec) 10 11 mysql>
很明顯是沒有使用到索引的,那么如何才能進行優化呢。需要注意的是,需要根據sql實際解析的順序,來調整索引的順序。
1 編寫過程:select distinct ... from ... join ... on ... where ... group by ... having ... order by ... limit ... 2 解析過程:from ... on ... join ... where ... group by ... having ... select distinct ... order by ... limit ...
如果索引順序是這樣的`user_age`, `user_name`, `user_account`,那么查詢的時候是使用了索引的,符合sql的解析過程,首先是where后面的字段,然后才是select后面的字段。
1 INDEX `user_age_name_account`(`user_age`, `user_name`, `user_account`) USING BTREE
1 mysql> EXPLAIN 2 -> SELECT user_account from user_info WHERE user_age in (22,23) and user_name = '小別同志' ORDER BY user_age; 3 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+ 6 | 1 | SIMPLE | user_info | NULL | range | user_age_name_account | user_age_name_account | 38 | NULL | 2 | 100.00 | Using where; Using index | 7 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql>
如果是查詢出所有的字段,就沒有進行回表查詢的,如下所示:
1 mysql> explain SELECT * from user_info WHERE user_age in (22,23) and user_name = '小別同志' ORDER BY user_age; 2 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ 3 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ 5 | 1 | SIMPLE | user_info | NULL | range | user_age_name_account | user_age_name_account | 38 | NULL | 2 | 100.00 | Using index condition | 6 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ 7 1 row in set, 1 warning (0.00 sec) 8 9 mysql>
索引一旦進行升級優化,需要將之前廢棄的索引刪除掉,防止干擾。
如果索引順序是這樣的`user_account`, `user_age`, `user_name`,也使用到了索引,但是進行了Using filesort,查詢行數rows由2變成了21,效率下降了。
1 INDEX `user_account_age_name`(`user_account`, `user_age`, `user_name`) USING BTREE
1 mysql> EXPLAIN 2 -> SELECT user_account from user_info WHERE user_age in (22,23) and user_name = '小別同志' ORDER BY user_age; 3 +----+-------------+-----------+------------+-------+---------------+-----------------------+---------+------+------+----------+------------------------------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+-------+---------------+-----------------------+---------+------+------+----------+------------------------------------------+ 6 | 1 | SIMPLE | user_info | NULL | index | NULL | user_account_age_name | 86 | NULL | 21 | 4.76 | Using where; Using index; Using filesort | 7 +----+-------------+-----------+------------+-------+---------------+-----------------------+---------+------+------+----------+------------------------------------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql>
索引級別type最好達到ref或者range級別的,可以再次進行優化,這里效果不明顯,但是in的范圍查詢可能會導致索引失效,最好放到后面,如下所示:
1 mysql> EXPLAIN 2 -> SELECT user_account from user_info WHERE user_name = '小別同志' and user_age in (22,23) ORDER BY user_age; 3 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+ 6 | 1 | SIMPLE | user_info | NULL | range | user_age_name_account | user_age_name_account | 38 | NULL | 2 | 100.00 | Using where; Using index | 7 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+--------------------------+ 8 1 row in set, 1 warning (0.00 sec) 9 10 mysql>
總結:mysql的索引不能跨列使用即跳過中間的索引字段(最佳左前綴),保持索引的定義和使用的順序一致性。索引需要逐步進行優化,將含In的范圍查詢放到where條件的最后,防止失效,如果失效了就需要回原表進行查詢了。
此案例中同時出現了Using where需要回原表查詢,Using index不需要回原表查詢,是因為in范圍查詢可能會導致索引失效就需要回原表進行查詢了,如果where后面的字段在索引中就不需要回原表,可以在索引表中查詢到。
1 mysql> EXPLAIN SELECT user_account from user_info WHERE user_name = '小別同志' and user_age =23 ORDER BY user_age; 2 +----+-------------+-----------+------------+------+-----------------------+-----------------------+---------+-------------+------+----------+-------------+ 3 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 4 +----+-------------+-----------+------------+------+-----------------------+-----------------------+---------+-------------+------+----------+-------------+ 5 | 1 | SIMPLE | user_info | NULL | ref | user_name_age_account | user_name_age_account | 38 | const,const | 1 | 100.00 | Using index | 6 +----+-------------+-----------+------------+------+-----------------------+-----------------------+---------+-------------+------+----------+-------------+ 7 1 row in set, 1 warning (0.00 sec) 8 9 mysql>
10、mysql的雙表索引優化案例,如下所示:
1 SET NAMES utf8mb4; 2 SET FOREIGN_KEY_CHECKS = 0; 3 4 -- ---------------------------- 5 -- Table structure for book_info 6 -- ---------------------------- 7 DROP TABLE IF EXISTS `book_info`; 8 CREATE TABLE `book_info` ( 9 `book_id` int(11) NOT NULL COMMENT '圖書編號', 10 `book_sort_id` int(11) DEFAULT NULL COMMENT '圖書類型編號', 11 `book_name` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書名稱', 12 `book_author` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書作者', 13 `book_price` decimal(5, 2) DEFAULT NULL COMMENT '圖書價格', 14 `book_type` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書類型', 15 `book_publish` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書出版社', 16 `book_sum` int(255) DEFAULT NULL COMMENT '圖書數量', 17 `book_mark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書標識', 18 `create_time` datetime(0) DEFAULT CURRENT_TIMESTAMP COMMENT '圖書創建時間', 19 `book_money` decimal(5, 2) DEFAULT NULL COMMENT '圖書租金', 20 `book_desc` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '圖書說明' 21 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '圖書信息表' ROW_FORMAT = Dynamic; 22 23 -- ---------------------------- 24 -- Table structure for book_sort 25 -- ---------------------------- 26 DROP TABLE IF EXISTS `book_sort`; 27 CREATE TABLE `book_sort` ( 28 `book_sort_id` int(11) NOT NULL COMMENT '圖書類別編號', 29 `book_sort_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書類別名稱', 30 `book_sort_extend` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書類別擴展信息', 31 `book_sort_mark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '圖書類別標識', 32 `create_time` datetime(0) DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間' 33 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '圖書類別表' ROW_FORMAT = Dynamic; 34 35 SET FOREIGN_KEY_CHECKS = 1;
兩張表組合查詢,進行左外關聯,如下所示:
Using join buffer (Block Nested Loop),extra中的一個選項,作用就是mysql的引擎使用了連接緩存,其實就是你的sql太差了,mysql給你添加了一個緩存。
1 mysql> EXPLAIN 2 -> SELECT * from book_info bi LEFT OUTER JOIN book_sort bs ON bi.book_sort_id = bs.book_sort_id WHERE bi.book_name = 'Java'; 3 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+ 6 | 1 | SIMPLE | bi | NULL | ALL | NULL | NULL | NULL | NULL | 16 | 10.00 | Using where | 7 | 1 | SIMPLE | bs | NULL | ALL | NULL | NULL | NULL | NULL | 9 | 100.00 | Using where; Using join buffer (Block Nested Loop) | 8 +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+ 9 2 rows in set, 1 warning (0.01 sec) 10 11 mysql>
對於兩張表的關聯查詢,索引向那張表加呢,這里有一個原則,叫做小表驅動大表,即where后面跟的是,小表放左邊,大表放右表。索引建立到經常使用的字段上。一般情況下,對於左外連接,給左表加索引,右外連接給右表加索引。
此時可以將左表的查詢字段添加上索引,增加查詢速度。
1 mysql> EXPLAIN 2 -> SELECT * from book_info bi LEFT OUTER JOIN book_sort bs ON bi.book_sort_id = bs.book_sort_id WHERE bi.book_name = 'Java'; 3 +----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+ 6 | 1 | SIMPLE | bi | NULL | ref | book_name | book_name | 48 | const | 1 | 100.00 | NULL | 7 | 1 | SIMPLE | bs | NULL | ALL | NULL | NULL | NULL | NULL | 21 | 100.00 | Using where; Using join buffer (Block Nested Loop) | 8 +----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+ 9 2 rows in set, 1 warning (0.00 sec) 10 11 mysql> 12 mysql>
如果此時右表的book_sort_id添加主鍵索引,此時兩條都使用了索引查詢,增加了查詢效率,如下所示:
1 mysql> EXPLAIN 2 -> SELECT * from book_info bi LEFT OUTER JOIN book_sort bs ON bi.book_sort_id = bs.book_sort_id WHERE bi.book_name = 'Java'; 3 +----+-------------+-------+------------+--------+---------------+-----------+---------+----------------------+------+----------+-------+ 4 | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | 5 +----+-------------+-------+------------+--------+---------------+-----------+---------+----------------------+------+----------+-------+ 6 | 1 | SIMPLE | bi | NULL | ref | book_name | book_name | 48 | const | 1 | 100.00 | NULL | 7 | 1 | SIMPLE | bs | NULL | eq_ref | PRIMARY | PRIMARY | 4 | book.bi.book_sort_id | 1 | 100.00 | NULL | 8 +----+-------------+-------+------------+--------+---------------+-----------+---------+----------------------+------+----------+-------+ 9 2 rows in set, 1 warning (0.01 sec) 10 11 mysql>
11、避免mysql索引失效的一些原則。sql優化,是一種概率層面的優化,至於是否實際使用了我們的優化,需要通過explain進行推測。索引優化,是一個大部分情況適用的結論,但是由於SQL優化器等原因,該結論不是100%正確的。
1)、復合索引的時候不要跨列或者無序使用(最佳左前綴原則)。復合索引,盡量使用全索引匹配。對於復合索引,如果前面的字段索引失效,后面的字段索引就失效了。
2)、不要在索引上進行任何操作(進行計算,函數,類型轉換),否則索引失效。
3)、復合索引不能使用不等於(!= 或者 <>)或者is null(is not null),否則自身以及右側所有全部失效。復合索引中如果有>大於號,則自身和右側索引全部失效。一般而言,范圍查詢>、<、in之后的索引失效。
4)、like盡量以"常量"開頭,不要以'%'開頭,可以將%加到常量的后面,否則索引失效。如果非要以%開頭,可以使用索引覆蓋,即模糊查詢的字段作為查詢出的字段,不用回表查詢。
5)、盡量不要使用類型轉換(顯式轉換、隱式轉換),否則都會使索引失效。
6)、盡量不要使用or,否則索引失效。會將or左側的索引失效了。
7)、對於exist和in,如果主查詢的數據集大,則使用In,此時In的效率高些。如果子查詢的數據集大,則使用exist,此時exist的效率高些。exist的含義就是將主查詢的結果,放到子查詢的結果中進行校驗(看子查詢是否有數據,如果有數據,則校驗成功),如果復合校驗,則保留數據。
8)、order by優化,using filesort有兩種算法,雙路排序、單路排序(根據IO的次數)。Mysql4.1之前默認使用的是雙路排序,Mysql4.1之后使用的是單路排序。雙路就是兩次IO,會掃描兩次磁盤,第一次從磁盤讀取排序字段,對排序字段進行排序,第二次掃描其他字段,IO消耗性能。單路排序只讀取一次,這一次就是全部的字段,在buffer中進行排序,但是單路排序,會有一定的隱患,不一定是真的一次IO,有可能是多次IO,如果數據量特別大,則無法將所有字段的數據一次性讀取完畢,因此會進行分片讀取。注意,單路排序會比雙路排序占用更多的buffer,單路排序在使用的時候,如果數據量過大,可以考慮調大buffer的容量大小,set max_length_for_sort_data=1024,單位是字節。如果max_length_for_sort_data值太低,則mysql會自動從單路切換到雙路,太低的條件是需要排序的列的總大小超過了max_length_for_sort_data定義的字節數。
總結:提高order by查詢的策略,可以選擇使用單路,雙路,調整buffer的容量大小。避免select *的查詢,只查詢出需要的字段即可。復合索引,不要跨列使用,避免出現using filesort。保證全部的排序字段排序的一致性,都是升序排序或者都是降序排列。
12、mysql的慢查詢日志,mysql提供的一種日志記錄,用於記錄mysql中響應時間超過閾值的sql語句long_query_time,默認是10秒。慢查詢日志默認是關閉的,建議,在開發調優的時候打開,項目上線關閉即可。
檢查是否開啟了慢查詢日志,如下所示:
1 mysql> show variables like '%slow_query_log%'; 2 +---------------------+-----------------------------------+ 3 | Variable_name | Value | 4 +---------------------+-----------------------------------+ 5 | slow_query_log | OFF | 6 | slow_query_log_file | /var/lib/mysql/k8s-node3-slow.log | 7 +---------------------+-----------------------------------+ 8 2 rows in set (0.00 sec) 9 10 mysql>
開啟mysql的慢查詢日志,臨時開啟,重啟mysql就關閉mysql的慢查詢了,在內存中開啟,如下所示:
1 mysql> set global slow_query_log = 1; 2 Query OK, 0 rows affected (0.02 sec) 3 4 mysql> show variables like '%slow_query_log%'; 5 +---------------------+-----------------------------------+ 6 | Variable_name | Value | 7 +---------------------+-----------------------------------+ 8 | slow_query_log | ON | 9 | slow_query_log_file | /var/lib/mysql/k8s-node3-slow.log | 10 +---------------------+-----------------------------------+ 11 2 rows in set (0.01 sec) 12 13 mysql>
開啟mysql的慢查詢日志,永久開啟,修改配置文件/etc/my.cnf,如下所示:
1 [mysqld] 2 slow_query_log=1 3 slow_query_log_file=/var/lib/mysql/localhost-slow.log
重啟mysql,然后查看是否已經開啟了慢查詢,如下所示:
1 [root@k8s-node3 ~]# vim /etc/my.cnf 2 [root@k8s-node3 ~]# systemctl restart mysqld.service 3 [root@k8s-node3 ~]# mysql -uroot -h127.0.0.1 -p123456 4 mysql: [Warning] Using a password on the command line interface can be insecure. 5 Welcome to the MySQL monitor. Commands end with ; or \g. 6 Your MySQL connection id is 2 7 Server version: 5.7.30-log MySQL Community Server (GPL) 8 9 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 10 11 Oracle is a registered trademark of Oracle Corporation and/or its 12 affiliates. Other names may be trademarks of their respective 13 owners. 14 15 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 16 17 mysql> show variables like '%slow_query_log%'; 18 +---------------------+-----------------------------------+ 19 | Variable_name | Value | 20 +---------------------+-----------------------------------+ 21 | slow_query_log | ON | 22 | slow_query_log_file | /var/lib/mysql/localhost-slow.log | 23 +---------------------+-----------------------------------+ 24 2 rows in set (0.01 sec) 25 26 mysql>
查看慢查詢的默認超時時間,默認超時時間是10秒鍾,如下所示:
1 mysql> show variables like '%long_query_time%'; 2 +-----------------+-----------+ 3 | Variable_name | Value | 4 +-----------------+-----------+ 5 | long_query_time | 10.000000 | 6 +-----------------+-----------+ 7 1 row in set (0.00 sec) 8 9 mysql>
mysql的慢查詢日志,臨時超時閾值時間設置set global long_query_time = 5.000000;,需要重新登錄mysql才生效,如下所示:
1 mysql> show variables like '%long_query_time%'; 2 +-----------------+-----------+ 3 | Variable_name | Value | 4 +-----------------+-----------+ 5 | long_query_time | 10.000000 | 6 +-----------------+-----------+ 7 1 row in set (0.00 sec) 8 9 mysql> set global long_query_time = 5.000000; 10 Query OK, 0 rows affected (0.00 sec) 11 12 mysql> show variables like '%long_query_time%'; 13 +-----------------+-----------+ 14 | Variable_name | Value | 15 +-----------------+-----------+ 16 | long_query_time | 10.000000 | 17 +-----------------+-----------+ 18 1 row in set (0.00 sec) 19 20 mysql> exit; 21 Bye 22 [root@k8s-node3 ~]# mysql -uroot -h127.0.0.1 -p123456 23 mysql: [Warning] Using a password on the command line interface can be insecure. 24 Welcome to the MySQL monitor. Commands end with ; or \g. 25 Your MySQL connection id is 3 26 Server version: 5.7.30-log MySQL Community Server (GPL) 27 28 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 29 30 Oracle is a registered trademark of Oracle Corporation and/or its 31 affiliates. Other names may be trademarks of their respective 32 owners. 33 34 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 35 36 mysql> show variables like '%long_query_time%'; 37 +-----------------+----------+ 38 | Variable_name | Value | 39 +-----------------+----------+ 40 | long_query_time | 5.000000 | 41 +-----------------+----------+ 42 1 row in set (0.00 sec) 43 44 mysql>
mysql的慢查詢日志,永久超時閾值時間設置,需要重啟mysql服務,如下所示:
1 [mysqld] 2 slow_query_log=1 3 slow_query_log_file=/var/lib/mysql/localhost-slow.log 4 long_query_time=3
重啟mysql服務,如下所示:
1 [root@k8s-node3 ~]# systemctl restart mysqld.service 2 [root@k8s-node3 ~]# mysql -uroot -h127.0.0.1 -p123456 3 mysql: [Warning] Using a password on the command line interface can be insecure. 4 Welcome to the MySQL monitor. Commands end with ; or \g. 5 Your MySQL connection id is 2 6 Server version: 5.7.30-log MySQL Community Server (GPL) 7 8 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 9 10 Oracle is a registered trademark of Oracle Corporation and/or its 11 affiliates. Other names may be trademarks of their respective 12 owners. 13 14 Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 15 16 mysql> show variables like '%long_query_time%'; 17 +-----------------+----------+ 18 | Variable_name | Value | 19 +-----------------+----------+ 20 | long_query_time | 3.000000 | 21 +-----------------+----------+ 22 1 row in set (0.00 sec) 23 24 mysql>
mysql的慢查詢日志,查看慢查詢的條數,如下所示:
1 mysql> select sleep(4); 2 +----------+ 3 | sleep(4) | 4 +----------+ 5 | 0 | 6 +----------+ 7 1 row in set (4.01 sec) 8 9 mysql> show global status like '%slow_queries%'; 10 +---------------+-------+ 11 | Variable_name | Value | 12 +---------------+-------+ 13 | Slow_queries | 1 | 14 +---------------+-------+ 15 1 row in set (0.00 sec) 16 17 mysql>
慢查詢的sql被記錄在了日志中,我們可以通過日志查看具體的慢sql,目錄var/lib/mysql/localhost-slow.log是我們自己配置的,如下所示:
1 [root@k8s-node3 ~]# cat /var/lib/mysql/localhost-slow.log 2 /usr/sbin/mysqld, Version: 5.7.30-log (MySQL Community Server (GPL)). started with: 3 Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sock 4 Time Id Command Argument 5 /usr/sbin/mysqld, Version: 5.7.30-log (MySQL Community Server (GPL)). started with: 6 Tcp port: 0 Unix socket: /var/lib/mysql/mysql.sock 7 Time Id Command Argument 8 # Time: 2020-07-19T13:24:44.111649Z 9 # User@Host: root[root] @ localhost [127.0.0.1] Id: 2 10 # Query_time: 4.003324 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 0 11 SET timestamp=1595165084; 12 select sleep(4); 13 [root@k8s-node3 ~]#
也可以通過mysqldumpslow工具查看慢sql,此是mysql自帶的工具,s代表了排序方式,r代表了逆序,l代表了鎖定時間,g代表了正則匹配模式,如下所示:
1 [root@k8s-node3 ~]# mysqldumpslow --help 2 Usage: mysqldumpslow [ OPTS... ] [ LOGS... ] 3 4 Parse and summarize the MySQL slow query log. Options are 5 6 --verbose verbose 7 --debug debug 8 --help write this text to standard output 9 10 -v verbose 11 -d debug 12 -s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default 13 al: average lock time 14 ar: average rows sent 15 at: average query time 16 c: count 17 l: lock time 18 r: rows sent 19 t: query time 20 -r reverse the sort order (largest last instead of first) 21 -t NUM just show the top n queries 22 -a don't abstract all numbers to N and strings to 'S' 23 -n NUM abstract numbers with at least n digits within names 24 -g PATTERN grep: only consider stmts that include this string 25 -h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard), 26 default is '*', i.e. match all 27 -i NAME name of server instance (if using mysql.server startup script) 28 -l don't subtract lock time from total time 29 30 [root@k8s-node3 ~]#
mysqldumpslow具體使用,如下所示:
1 [root@k8s-node3 ~]# mysqldumpslow -s -r -t 3 /var/lib/mysql/localhost-slow.log 2 3 Reading mysql slow query log from /var/lib/mysql/localhost-slow.log 4 Count: 6 Time=4.33s (26s) Lock=0.00s (0s) Rows=1.0 (6), root[root]@localhost 5 select sleep(N) 6 7 Died at /usr/bin/mysqldumpslow line 167, <> chunk 6. 8 [root@k8s-node3 ~]# mysqldumpslow -s -c -t 3 /var/lib/mysql/localhost-slow.log 9 10 Reading mysql slow query log from /var/lib/mysql/localhost-slow.log 11 Count: 6 Time=4.33s (26s) Lock=0.00s (0s) Rows=1.0 (6), root[root]@localhost 12 select sleep(N) 13 14 Died at /usr/bin/mysqldumpslow line 167, <> chunk 6. 15 [root@k8s-node3 ~]# mysqldumpslow -s t -t 3 "left join" /var/lib/mysql/localhost-slow.log 16 17 Reading mysql slow query log from left join /var/lib/mysql/localhost-slow.log 18 Can't open left join: No such file or directory at /usr/bin/mysqldumpslow line 97. 19 Count: 6 Time=4.33s (26s) Lock=0.00s (0s) Rows=1.0 (6), root[root]@localhost 20 select sleep(N) 21 22 Died at /usr/bin/mysqldumpslow line 167, <> chunk 6. 23 [root@k8s-node3 ~]# mysqldumpslow -s t -t 3 -g "left join" /var/lib/mysql/localhost-slow.log 24 25 Reading mysql slow query log from /var/lib/mysql/localhost-slow.log 26 Died at /usr/bin/mysqldumpslow line 167, <> chunk 6. 27 [root@k8s-node3 ~]#
13、通過profiles分析mysql的海量數據。首先創建兩個數據表,如下所示:
1 SET NAMES utf8mb4; 2 SET FOREIGN_KEY_CHECKS = 0; 3 4 -- ---------------------------- 5 -- Table structure for dept 6 -- ---------------------------- 7 DROP TABLE IF EXISTS `dept`; 8 CREATE TABLE `dept` ( 9 `dno` int(11) NOT NULL, 10 `dname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 11 `location` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 12 PRIMARY KEY (`dno`) USING BTREE 13 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 14 15 -- ---------------------------- 16 -- Table structure for emp 17 -- ---------------------------- 18 DROP TABLE IF EXISTS `emp`; 19 CREATE TABLE `emp` ( 20 `eid` int(11) NOT NULL, 21 `ename` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 22 `job` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 23 `deptno` int(5) DEFAULT NULL, 24 PRIMARY KEY (`eid`) USING BTREE 25 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
創建一個存儲函數,方便海量插入數據,如下所示:
1 -- ---------------------------- 2 -- Function structure for randstring 3 -- ---------------------------- 4 DROP FUNCTION IF EXISTS `randstring`; 5 delimiter ;; 6 CREATE DEFINER=`root`@`localhost` FUNCTION `randstring`( n INT ) RETURNS varchar(255) CHARSET utf8 7 BEGIN 8 DECLARE 9 all_str VARCHAR ( 100 ) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 10 DECLARE 11 return_str VARCHAR ( 255 ) DEFAULT ''; 12 DECLARE 13 i INT DEFAULT 0; 14 WHILE 15 i < n DO 16 17 SET return_str = CONCAT( return_str, SUBSTRING( all_str, FLOOR( 1 + RAND( ) * 52 ), 1 ) ); 18 19 SET i = i + 1; 20 21 END WHILE; 22 RETURN return_str; 23 24 END 25 ;; 26 delimiter ; 27 28 SET FOREIGN_KEY_CHECKS = 1; 29 30 -- 執行,如下所示: 31 32 33 mysql> delimiter $ 34 mysql> CREATE FUNCTION randstring ( n INT ) RETURNS VARCHAR ( 255 ) BEGIN 35 -> DECLARE 36 -> all_str VARCHAR ( 100 ) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 37 -> DECLARE 38 -> return_str VARCHAR ( 255 ) DEFAULT ''; 39 -> DECLARE 40 -> i INT DEFAULT 0; 41 -> WHILE 42 -> i < n DO 43 -> 44 -> SET return_str = CONCAT( return_str, SUBSTRING( all_str, FLOOR( 1 + RAND( ) * 52 ), 1 ) ); 45 -> 46 -> SET i = i + 1; 47 -> 48 -> END WHILE; 49 -> RETURN return_str; 50 -> 51 -> END $ 52 Query OK, 0 rows affected (0.03 sec) 53 54 mysql>
創建一個生成隨機數0-99的存儲函數,如下所示:
1 -- 防止分號造成語義中斷。 2 3 delimiter $ 4 CREATE FUNCTION rand_num ( ) RETURNS INT ( 5 ) BEGIN 5 DECLARE 6 i INT DEFAULT 0; 7 8 SET i = FLOOR( rand( ) * 100 ); 9 RETURN i; 10 11 END $
通過存儲過程插入海量數據,把上面的兩個存儲函數使用上,注意,存儲函數有返回值,存儲過程沒有返回值,如下所示:
1 mysql> 2 mysql> delimiter $ 3 mysql> CREATE PROCEDURE insert_emp ( IN eid_start INT ( 10 ), IN data_times INT ( 10 ) ) BEGIN 4 -> DECLARE 5 -> i INT DEFAULT 0; 6 -> 7 -> SET autocommit = 0; 8 -> REPEAT 9 -> INSERT INTO emp 10 -> VALUES 11 -> ( eid_start + i, randstring ( 5 ), 'other', rand_num ( ) ); 12 -> 13 -> SET i = i + 1; 14 -> UNTIL i = data_times 15 -> END REPEAT; 16 -> COMMIT; 17 -> 18 -> END $ 19 Query OK, 0 rows affected (0.01 sec) 20 21 mysql>
1 mysql> 2 mysql> delimiter $ 3 mysql> CREATE PROCEDURE insert_dept ( IN dno_start INT ( 10 ), IN data_times INT ( 10 ) ) BEGIN 4 -> DECLARE 5 -> i INT DEFAULT 0; 6 -> 7 -> SET autocommit = 0; 8 -> REPEAT 9 -> INSERT INTO dept 10 -> VALUES 11 -> ( dno_start + i, randstring ( 6 ), randstring ( 8 ) ); 12 -> 13 -> SET i = i + 1; 14 -> UNTIL i = data_times 15 -> END REPEAT; 16 -> COMMIT; 17 -> 18 -> END $ 19 Query OK, 0 rows affected (0.00 sec) 20 21 mysql>
編寫好存儲過程之后,就可以開始調用存儲過程了,開始批量插入數據,如下所示:
1 mysql> delimiter ; 2 mysql> CALL insert_emp(1000,800000); 3 Query OK, 0 rows affected (1 min 8.33 sec) 4 5 mysql> 6 7 mysql> delimiter ; 8 mysql> CALL insert_dept(10,30); 9 Query OK, 0 rows affected (0.01 sec) 10 11 mysql> 12 13 mysql> select count(*) from emp; 14 +----------+ 15 | count(*) | 16 +----------+ 17 | 800000 | 18 +----------+ 19 1 row in set (0.22 sec) 20 21 mysql> select count(*) from dept; 22 +----------+ 23 | count(*) | 24 +----------+ 25 | 30 | 26 +----------+ 27 1 row in set (0.00 sec) 28 29 mysql>
海量數據已經生成了,這里通過profiles分析mysql的海量數據。 默認關閉,需要打開,如下所示:
1 mysql> show profiles; 2 Empty set, 1 warning (0.00 sec) 3 4 mysql> show variables like '%profiling%'; 5 +------------------------+-------+ 6 | Variable_name | Value | 7 +------------------------+-------+ 8 | have_profiling | YES | 9 | profiling | OFF | 10 | profiling_history_size | 15 | 11 +------------------------+-------+ 12 3 rows in set (0.04 sec) 13 14 mysql> set profiling = on; 15 Query OK, 0 rows affected, 1 warning (0.00 sec) 16 17 mysql> show variables like '%profiling%'; 18 +------------------------+-------+ 19 | Variable_name | Value | 20 +------------------------+-------+ 21 | have_profiling | YES | 22 | profiling | ON | 23 | profiling_history_size | 15 | 24 +------------------------+-------+ 25 3 rows in set (0.01 sec) 26 27 mysql> show profiles; 28 +----------+------------+-----------------------------------+ 29 | Query_ID | Duration | Query | 30 +----------+------------+-----------------------------------+ 31 | 1 | 0.00209325 | show variables like '%profiling%' | 32 +----------+------------+-----------------------------------+ 33 1 row in set, 1 warning (0.00 sec) 34 35 mysql>
show profiles會記錄所有profiling打開之后的的所有sql查詢語句。Query_ID是編號,Duration表示花費的時間,單位是秒,Query是查詢的語句。
1 mysql> show profiles; 2 +----------+------------+-----------------------------------+ 3 | Query_ID | Duration | Query | 4 +----------+------------+-----------------------------------+ 5 | 1 | 0.00209325 | show variables like '%profiling%' | 6 +----------+------------+-----------------------------------+ 7 1 row in set, 1 warning (0.00 sec) 8 9 mysql> select count(*) from dept; 10 +----------+ 11 | count(*) | 12 +----------+ 13 | 30 | 14 +----------+ 15 1 row in set (0.00 sec) 16 17 mysql> show profiles; 18 +----------+------------+-----------------------------------+ 19 | Query_ID | Duration | Query | 20 +----------+------------+-----------------------------------+ 21 | 1 | 0.00209325 | show variables like '%profiling%' | 22 | 2 | 0.00075825 | select count(*) from dept | 23 +----------+------------+-----------------------------------+ 24 2 rows in set, 1 warning (0.00 sec) 25 26 mysql>
缺點,是Duration顯示的時間不夠精准,只是將cpu、IO、內存等等消費的總和。只能看到總共消費的時間,不能看到各個硬件消費的時間。
如何進行精准分析呢,需要通過一個sql診斷show profile all for query 上一步查詢的Query_ID。
1 mysql> show profiles; 2 +----------+------------+-----------------------------------+ 3 | Query_ID | Duration | Query | 4 +----------+------------+-----------------------------------+ 5 | 1 | 0.00209325 | show variables like '%profiling%' | 6 | 2 | 0.00075825 | select count(*) from dept | 7 | 3 | 0.00071025 | select * from dept | 8 +----------+------------+-----------------------------------+ 9 3 rows in set, 1 warning (0.00 sec) 10 11 mysql> show profile all for query 3; 12 +----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+ 13 | Status | Duration | CPU_user | CPU_system | Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out | Messages_sent | Messages_received | Page_faults_major | Page_faults_minor | Swaps | Source_function | Source_file | Source_line | 14 +----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+ 15 | starting | 0.000102 | 0.000097 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | NULL | NULL | NULL | 16 | checking permissions | 0.000017 | 0.000012 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | check_access | sql_authorization.cc | 809 | 17 | Opening tables | 0.000061 | 0.000064 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | open_tables | sql_base.cc | 5781 | 18 | init | 0.000077 | 0.000077 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | handle_query | sql_select.cc | 128 | 19 | System lock | 0.000019 | 0.000016 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_lock_tables | lock.cc | 330 | 20 | optimizing | 0.000007 | 0.000006 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | optimize | sql_optimizer.cc | 158 | 21 | statistics | 0.000054 | 0.000058 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | optimize | sql_optimizer.cc | 374 | 22 | preparing | 0.000022 | 0.000018 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | optimize | sql_optimizer.cc | 482 | 23 | executing | 0.000005 | 0.000005 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | exec | sql_executor.cc | 126 | 24 | Sending data | 0.000164 | 0.000169 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | exec | sql_executor.cc | 202 | 25 | end | 0.000013 | 0.000009 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | handle_query | sql_select.cc | 206 | 26 | query end | 0.000009 | 0.000009 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_execute_command | sql_parse.cc | 4956 | 27 | closing tables | 0.000009 | 0.000009 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_execute_command | sql_parse.cc | 5009 | 28 | freeing items | 0.000115 | 0.000118 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | mysql_parse | sql_parse.cc | 5622 | 29 | cleaning up | 0.000037 | 0.000034 | 0.000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | dispatch_command | sql_parse.cc | 1931 | 30 +----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+ 31 15 rows in set, 1 warning (0.01 sec) 32 33 mysql>
如果只關心部分字段,可以進行部分字段的查詢,如下所示:
1 mysql> show profile cpu,block io for query 3; 2 +----------------------+----------+----------+------------+--------------+---------------+ 3 | Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out | 4 +----------------------+----------+----------+------------+--------------+---------------+ 5 | starting | 0.000102 | 0.000097 | 0.000000 | 0 | 0 | 6 | checking permissions | 0.000017 | 0.000012 | 0.000000 | 0 | 0 | 7 | Opening tables | 0.000061 | 0.000064 | 0.000000 | 0 | 0 | 8 | init | 0.000077 | 0.000077 | 0.000000 | 0 | 0 | 9 | System lock | 0.000019 | 0.000016 | 0.000000 | 0 | 0 | 10 | optimizing | 0.000007 | 0.000006 | 0.000000 | 0 | 0 | 11 | statistics | 0.000054 | 0.000058 | 0.000000 | 0 | 0 | 12 | preparing | 0.000022 | 0.000018 | 0.000000 | 0 | 0 | 13 | executing | 0.000005 | 0.000005 | 0.000000 | 0 | 0 | 14 | Sending data | 0.000164 | 0.000169 | 0.000000 | 0 | 0 | 15 | end | 0.000013 | 0.000009 | 0.000000 | 0 | 0 | 16 | query end | 0.000009 | 0.000009 | 0.000000 | 0 | 0 | 17 | closing tables | 0.000009 | 0.000009 | 0.000000 | 0 | 0 | 18 | freeing items | 0.000115 | 0.000118 | 0.000000 | 0 | 0 | 19 | cleaning up | 0.000037 | 0.000034 | 0.000000 | 0 | 0 | 20 +----------------------+----------+----------+------------+--------------+---------------+ 21 15 rows in set, 1 warning (0.00 sec) 22 23 mysql>
查看全局的查詢日志(默認關閉的,需要手動開啟),記錄開啟之后的,全部sql語句。這些全局的記錄操作,僅僅在調優和開發過程中打開即可,在正式環境要進行關閉的,如下所示:
1 mysql> show variables like '%general_log%'; 2 +------------------+------------------------------+ 3 | Variable_name | Value | 4 +------------------+------------------------------+ 5 | general_log | OFF | 6 | general_log_file | /var/lib/mysql/k8s-node3.log | 7 +------------------+------------------------------+ 8 2 rows in set (0.01 sec) 9 10 mysql> set global general_log = 1; 11 Query OK, 0 rows affected (0.00 sec) 12 13 mysql> show variables like '%general_log%'; 14 +------------------+------------------------------+ 15 | Variable_name | Value | 16 +------------------+------------------------------+ 17 | general_log | ON | 18 | general_log_file | /var/lib/mysql/k8s-node3.log | 19 +------------------+------------------------------+ 20 2 rows in set (0.00 sec) 21 22 mysql>
1 mysql> set global log_output='table'; 2 Query OK, 0 rows affected (0.00 sec)
開啟之后,會記錄所有的sql語句的,會被記錄到mysql.general_log數據表中,如下所示:
1 [root@k8s-node3 ~]# cat /var/lib/mysql/k8s-node3.log 2 /usr/sbin/mysqld, Version: 5.7.30-log (MySQL Community Server (GPL)). started with: 3 Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock 4 Time Id Command Argument 5 2020-07-20T07:07:09.834131Z 12 Query show variables like '%general_log%' 6 2020-07-20T07:07:57.165503Z 12 Query SELECT DATABASE() 7 2020-07-20T07:07:57.166003Z 12 Init DB bigdata 8 2020-07-20T07:07:57.168232Z 12 Query show databases 9 2020-07-20T07:07:57.169327Z 12 Query show tables 10 2020-07-20T07:07:57.169786Z 12 Field List dept 11 2020-07-20T07:07:57.171001Z 12 Field List emp 12 2020-07-20T07:07:59.196072Z 12 Query show tables 13 2020-07-20T07:08:11.721455Z 12 Query select * from dept 14 2020-07-20T07:08:19.914896Z 12 Query select * from emp limit 3000 15 2020-07-20T07:08:32.237933Z 12 Query show variables like '%general_log%' 16 [root@k8s-node3 ~]#
如果開啟了mysql> set global log_output='table';也可以查看mysql的數據表來查看sql語句,如下所示:
注意:這里既可以指定表也可以指定文件,看個人需求了:set global log_output='table';或者set global log_output='file';
1 mysql> select * from mysql.general_log; 2 +----------------------------+------------------------------------+-----------+-----------+--------------+---------------------------------+ 3 | event_time | user_host | thread_id | server_id | command_type | argument | 4 +----------------------------+------------------------------------+-----------+-----------+--------------+---------------------------------+ 5 | 2020-07-20 15:10:52.374558 | root[root] @ localhost [127.0.0.1] | 12 | 0 | Query | select * from mysql.general_log | 6 | 2020-07-20 15:11:27.112186 | root[root] @ localhost [127.0.0.1] | 12 | 0 | Query | select * from dept | 7 | 2020-07-20 15:11:30.430782 | root[root] @ localhost [127.0.0.1] | 12 | 0 | Query | select * from emp limit 3000 | 8 | 2020-07-20 15:11:32.430116 | root[root] @ localhost [127.0.0.1] | 12 | 0 | Query | select * from mysql.general_log | 9 +----------------------------+------------------------------------+-----------+-----------+--------------+---------------------------------+ 10 4 rows in set (0.00 sec) 11 12 mysql>
14、鎖機制,解決因資源共享而造成的並發問題。鎖的分類,根據操作類型分,可以分為讀鎖(讀鎖也稱為共享鎖)、寫鎖(寫鎖也稱為互斥鎖)。根據操作范圍來分,可以分為表級鎖、行級鎖、頁級鎖。
1 SET NAMES utf8mb4; 2 SET FOREIGN_KEY_CHECKS = 0; 3 4 -- ---------------------------- 5 -- Table structure for user 6 -- ---------------------------- 7 DROP TABLE IF EXISTS `user`; 8 CREATE TABLE `user` ( 9 `id` int(11) NOT NULL AUTO_INCREMENT, 10 `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 11 PRIMARY KEY (`id`) USING BTREE 12 ) ENGINE = MyISAM AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 13 14 -- ---------------------------- 15 -- Records of user 16 -- ---------------------------- 17 INSERT INTO `user` VALUES (1, '張三'); 18 INSERT INTO `user` VALUES (2, '李四'); 19 INSERT INTO `user` VALUES (3, '王五'); 20 INSERT INTO `user` VALUES (4, '趙六'); 21 INSERT INTO `user` VALUES (5, '孫七'); 22 23 SET FOREIGN_KEY_CHECKS = 1;
14.1、根據操作類型分,可以分為讀鎖、寫鎖。
1)、讀鎖(共享鎖):對同一個數據,多個讀操作可以同時進行,互不干擾。
2)、寫鎖(互斥鎖):如果當前寫操作沒有完畢,則無法進行其他的讀操作,寫操作。
14.2、根據操作范圍來分,可以分為表級鎖、行級鎖、頁級鎖。
1)、表級鎖:一次性對一張表整體加鎖。MyISAM存儲引擎(開銷小,加鎖快,缺點就是鎖的范圍大容易發生鎖沖突,並發度低),是表級鎖,性能優化。
2)、行級鎖:一次性對一行數據進行加鎖。InnoDB存儲引擎(開銷大,加鎖慢,容易出現死鎖,鎖的范圍較小,不易發生鎖沖突,並發度高,很小的概率發生高並發問題,這些問題分別是臟讀、幻讀、不可重復讀、丟失更新),是行級鎖,事務優先,適合高並發操作。
14.3、如何查看加鎖的表呢,如下所示:
1 mysql> show open tables; 2 +--------------------+------------------------------------------------------+--------+-------------+ 3 | Database | Table | In_use | Name_locked | 4 +--------------------+------------------------------------------------------+--------+-------------+ 5 | performance_schema | events_waits_summary_by_user_by_event_name | 0 | 0 | 6 | performance_schema | events_waits_summary_global_by_event_name | 0 | 0 | 7 | performance_schema | events_transactions_summary_global_by_event_name | 0 | 0 | 8 | performance_schema | replication_connection_status | 0 | 0 | 9 | performance_schema | events_waits_summary_by_account_by_event_name | 0 | 0 | 10 | mysql | engine_cost | 0 | 0 | 11 | performance_schema | metadata_locks | 0 | 0 | 12 | performance_schema | status_by_user | 0 | 0 | 13 | performance_schema | replication_group_member_stats | 0 | 0 | 14 | performance_schema | events_statements_summary_by_account_by_event_name | 0 | 0 | 15 | performance_schema | socket_summary_by_event_name | 0 | 0 | 16 | performance_schema | prepared_statements_instances | 0 | 0 | 17 | performance_schema | events_statements_history_long | 0 | 0 | 18 | performance_schema | objects_summary_global_by_type | 0 | 0 | 19 | performance_schema | file_instances | 0 | 0 | 20 | performance_schema | events_stages_summary_by_user_by_event_name | 0 | 0 | 21 | performance_schema | memory_summary_by_thread_by_event_name | 0 | 0 | 22 | performance_schema | events_stages_history_long | 0 | 0 | 23 | performance_schema | cond_instances | 0 | 0 | 24 | performance_schema | global_status | 0 | 0 | 25 | performance_schema | socket_summary_by_instance | 0 | 0 | 26 | book | user_info | 0 | 0 | 27 | performance_schema | session_status | 0 | 0 | 28 | performance_schema | session_connect_attrs | 0 | 0 | 29 | mysql | plugin | 0 | 0 | 30 | mysql | time_zone_name | 0 | 0 | 31 | performance_schema | events_statements_summary_by_program | 0 | 0 | 32 | performance_schema | events_stages_current | 0 | 0 | 33 | performance_schema | setup_instruments | 0 | 0 | 34 | book | book_sort | 0 | 0 | 35 | book | book_recommendation | 0 | 0 | 36 | mysql | func | 0 | 0 | 37 | performance_schema | events_waits_history_long | 0 | 0 | 38 | performance_schema | rwlock_instances | 0 | 0 | 39 | mysql | time_zone_leap_second | 0 | 0 | 40 | performance_schema | table_io_waits_summary_by_table | 0 | 0 | 41 | performance_schema | events_transactions_summary_by_account_by_event_name | 0 | 0 | 42 | mysql | time_zone_transition_type | 0 | 0 | 43 | performance_schema | events_waits_current | 0 | 0 | 44 | performance_schema | replication_connection_configuration | 0 | 0 | 45 | mysql | procs_priv | 0 | 0 | 46 | performance_schema | events_transactions_summary_by_user_by_event_name | 0 | 0 | 47 | performance_schema | replication_applier_configuration | 0 | 0 | 48 | performance_schema | events_statements_summary_by_user_by_event_name | 0 | 0 | 49 | performance_schema | events_stages_summary_global_by_event_name | 0 | 0 | 50 | performance_schema | replication_applier_status_by_worker | 0 | 0 | 51 | performance_schema | events_waits_summary_by_thread_by_event_name | 0 | 0 | 52 | performance_schema | session_account_connect_attrs | 0 | 0 | 53 | performance_schema | performance_timers | 0 | 0 | 54 | performance_schema | setup_consumers | 0 | 0 | 55 | performance_schema | events_statements_history | 0 | 0 | 56 | bigdata | emp | 0 | 0 | 57 | performance_schema | global_variables | 0 | 0 | 58 | mysql | gtid_executed | 0 | 0 | 59 | mysql | columns_priv | 0 | 0 | 60 | performance_schema | events_transactions_summary_by_thread_by_event_name | 0 | 0 | 61 | performance_schema | replication_applier_status_by_coordinator | 0 | 0 | 62 | mysql | db | 0 | 0 | 63 | mysql | general_log | 0 | 0 | 64 | performance_schema | events_stages_summary_by_account_by_event_name | 0 | 0 | 65 | performance_schema | variables_by_thread | 0 | 0 | 66 | book | user_book | 0 | 0 | 67 | performance_schema | events_stages_history | 0 | 0 | 68 | bigdata | dept | 0 | 0 | 69 | performance_schema | socket_instances | 0 | 0 | 70 | performance_schema | table_lock_waits_summary_by_table | 0 | 0 | 71 | mysql | time_zone | 0 | 0 | 72 | performance_schema | events_statements_summary_by_thread_by_event_name | 0 | 0 | 73 | performance_schema | users | 0 | 0 | 74 | performance_schema | setup_timers | 0 | 0 | 75 | performance_schema | memory_summary_by_host_by_event_name | 0 | 0 | 76 | performance_schema | setup_objects | 0 | 0 | 77 | performance_schema | host_cache | 0 | 0 | 78 | performance_schema | status_by_account | 0 | 0 | 79 | mysql | proxies_priv | 0 | 0 | 80 | performance_schema | memory_summary_by_account_by_event_name | 0 | 0 | 81 | performance_schema | accounts | 0 | 0 | 82 | performance_schema | replication_group_members | 0 | 0 | 83 | mysql | tables_priv | 0 | 0 | 84 | performance_schema | events_stages_summary_by_host_by_event_name | 0 | 0 | 85 | performance_schema | events_statements_current | 0 | 0 | 86 | mysql | proc | 0 | 0 | 87 | performance_schema | events_waits_summary_by_instance | 0 | 0 | 88 | performance_schema | events_statements_summary_by_host_by_event_name | 0 | 0 | 89 | performance_schema | memory_summary_by_user_by_event_name | 0 | 0 | 90 | performance_schema | events_transactions_history | 0 | 0 | 91 | mysql | event | 0 | 0 | 92 | performance_schema | status_by_host | 0 | 0 | 93 | performance_schema | setup_actors | 0 | 0 | 94 | performance_schema | threads | 0 | 0 | 95 | performance_schema | events_statements_summary_global_by_event_name | 0 | 0 | 96 | performance_schema | status_by_thread | 0 | 0 | 97 | performance_schema | file_summary_by_event_name | 0 | 0 | 98 | performance_schema | mutex_instances | 0 | 0 | 99 | performance_schema | table_handles | 0 | 0 | 100 | performance_schema | session_variables | 0 | 0 | 101 | bigdata | user | 0 | 0 | 102 | book | book_info | 0 | 0 | 103 | performance_schema | events_transactions_current | 0 | 0 | 104 | performance_schema | user_variables_by_thread | 0 | 0 | 105 | mysql | time_zone_transition | 0 | 0 | 106 | performance_schema | table_io_waits_summary_by_index_usage | 0 | 0 | 107 | performance_schema | events_transactions_history_long | 0 | 0 | 108 | performance_schema | memory_summary_global_by_event_name | 0 | 0 | 109 | performance_schema | events_statements_summary_by_digest | 0 | 0 | 110 | performance_schema | events_transactions_summary_by_host_by_event_name | 0 | 0 | 111 | performance_schema | events_waits_history | 0 | 0 | 112 | mysql | user | 0 | 0 | 113 | performance_schema | events_waits_summary_by_host_by_event_name | 0 | 0 | 114 | performance_schema | events_stages_summary_by_thread_by_event_name | 0 | 0 | 115 | performance_schema | file_summary_by_instance | 0 | 0 | 116 | mysql | server_cost | 0 | 0 | 117 | performance_schema | hosts | 0 | 0 | 118 | performance_schema | replication_applier_status | 0 | 0 | 119 | mysql | servers | 0 | 0 | 120 +--------------------+------------------------------------------------------+--------+-------------+ 121 115 rows in set (0.01 sec) 122 123 mysql>
如何加鎖呢,如是,lock table 表1 read/write,表2 read/write...。首先研究的是MyISAM存儲引擎的讀鎖,讀鎖(共享鎖):對同一個數據,多個讀操作可以同時進行,互不干擾。
1 mysql> lock table user read; 2 Query OK, 0 rows affected (0.00 sec) 3 4 mysql> select * from user; 5 +----+--------+ 6 | id | name | 7 +----+--------+ 8 | 1 | 張三 | 9 | 2 | 李四 | 10 | 3 | 王五 | 11 | 4 | 趙六 | 12 | 5 | 孫七 | 13 +----+--------+ 14 5 rows in set (0.00 sec) 15 16 mysql>
加了讀鎖,是不可以進行寫的(寫操作就是增加、修改、刪除),讀就是查詢。
1 mysql> delete from user where id = 1; 2 ERROR 1099 (HY000): Table 'user' was locked with a READ lock and can't be updated 3 mysql>
總結:MyISAM存儲引擎,如果某一個會話,對A表加了read鎖,則該會話可以對A表進行讀操作,不能進行寫操作,且該會話不能對其他表進行讀、寫操作。會話0給A表加了鎖,其它會話,是可以對其他表(A表以外的表)進行讀、寫操作。對A表是可以讀的,但是寫操作的時候需要等待讀鎖的釋放。
14.4、加寫鎖,會話0加寫鎖,如下所示:
總結:當前會話即會話0,可以對加了寫鎖的表進行任何操作(增刪改查操作),但是不能操作(增刪改查)其他表。對會話0中加寫鎖的表,可以進行增刪改查的前提是,等待會話0釋放寫鎖。
14.5、Mysql中表級鎖的鎖模式,MyISAM在執行查詢語句Select前,會自動給涉及到的所有表加讀鎖,在執行更新操作DML前,會自動給涉及的表加寫鎖。所以對MyISAM表進行操作的時候會有以下情況:
a、對MyISAM表的讀操作(加讀鎖),不會阻塞其他進程(會話)對同一表的讀請求,但會阻塞對同一表的寫請求。只有當讀鎖釋放后,才會執行其他進程的寫操作。
b、對MyISAM表的寫操作(加寫鎖),會阻塞其他進程(會話)對同一表的讀和寫操作,只有當寫鎖釋放后,才會執行其他進程的讀寫操作。
15、表鎖情況分析及行鎖解析,分析表鎖定。
1)、查看那些表加了鎖:show open tables;其中1代表加了鎖。
2)、分析表鎖定的嚴重程度:show status like 'table%';其中Table_locks_immediate表示立刻可以獲取到的鎖。Table_locks_waited代表了需要等待的表鎖數,如果該值越大說明存在越大的鎖競爭。
3)、一般建議使用Table_locks_immediate/Table_locks_waited比率來看,如果大於5000采用InnoDB引擎,如果小於5000采用MyISAM存儲引擎。表鎖是通過unlock tables解鎖的,也可以通過事務進行解鎖的,行鎖是通過事務commit/rollback解鎖的。
1 mysql> show open tables; 2 +--------------------+------------------------------------------------------+--------+-------------+ 3 | Database | Table | In_use | Name_locked | 4 +--------------------+------------------------------------------------------+--------+-------------+ 5 | performance_schema | events_waits_summary_by_user_by_event_name | 0 | 0 | 6 | performance_schema | events_waits_summary_global_by_event_name | 0 | 0 | 7 | performance_schema | events_transactions_summary_global_by_event_name | 0 | 0 | 8 | performance_schema | replication_connection_status | 0 | 0 | 9 | performance_schema | events_waits_summary_by_account_by_event_name | 0 | 0 | 10 | mysql | engine_cost | 0 | 0 | 11 | performance_schema | metadata_locks | 0 | 0 | 12 | performance_schema | status_by_user | 0 | 0 | 13 | performance_schema | replication_group_member_stats | 0 | 0 | 14 | performance_schema | events_statements_summary_by_account_by_event_name | 0 | 0 | 15 | performance_schema | socket_summary_by_event_name | 0 | 0 | 16 | performance_schema | prepared_statements_instances | 0 | 0 | 17 | performance_schema | events_statements_history_long | 0 | 0 | 18 | performance_schema | objects_summary_global_by_type | 0 | 0 | 19 | performance_schema | file_instances | 0 | 0 | 20 | performance_schema | events_stages_summary_by_user_by_event_name | 0 | 0 | 21 | performance_schema | memory_summary_by_thread_by_event_name | 0 | 0 | 22 | performance_schema | events_stages_history_long | 0 | 0 | 23 | performance_schema | cond_instances | 0 | 0 | 24 | performance_schema | global_status | 0 | 0 | 25 | performance_schema | socket_summary_by_instance | 0 | 0 | 26 | book | user_info | 0 | 0 | 27 | performance_schema | session_status | 0 | 0 | 28 | performance_schema | session_connect_attrs | 0 | 0 | 29 | mysql | plugin | 0 | 0 | 30 | mysql | time_zone_name | 0 | 0 | 31 | performance_schema | events_statements_summary_by_program | 0 | 0 | 32 | performance_schema | events_stages_current | 0 | 0 | 33 | performance_schema | setup_instruments | 0 | 0 | 34 | book | book_sort | 0 | 0 | 35 | book | book_recommendation | 0 | 0 | 36 | mysql | func | 0 | 0 | 37 | performance_schema | events_waits_history_long | 0 | 0 | 38 | performance_schema | rwlock_instances | 0 | 0 | 39 | mysql | time_zone_leap_second | 0 | 0 | 40 | performance_schema | table_io_waits_summary_by_table | 0 | 0 | 41 | performance_schema | events_transactions_summary_by_account_by_event_name | 0 | 0 | 42 | mysql | time_zone_transition_type | 0 | 0 | 43 | performance_schema | events_waits_current | 0 | 0 | 44 | performance_schema | replication_connection_configuration | 0 | 0 | 45 | mysql | procs_priv | 0 | 0 | 46 | performance_schema | events_transactions_summary_by_user_by_event_name | 0 | 0 | 47 | performance_schema | replication_applier_configuration | 0 | 0 | 48 | performance_schema | events_statements_summary_by_user_by_event_name | 0 | 0 | 49 | performance_schema | events_stages_summary_global_by_event_name | 0 | 0 | 50 | performance_schema | replication_applier_status_by_worker | 0 | 0 | 51 | performance_schema | events_waits_summary_by_thread_by_event_name | 0 | 0 | 52 | performance_schema | session_account_connect_attrs | 0 | 0 | 53 | performance_schema | performance_timers | 0 | 0 | 54 | performance_schema | setup_consumers | 0 | 0 | 55 | performance_schema | events_statements_history | 0 | 0 | 56 | bigdata | emp | 0 | 0 | 57 | performance_schema | global_variables | 0 | 0 | 58 | mysql | gtid_executed | 0 | 0 | 59 | mysql | columns_priv | 0 | 0 | 60 | performance_schema | events_transactions_summary_by_thread_by_event_name | 0 | 0 | 61 | performance_schema | replication_applier_status_by_coordinator | 0 | 0 | 62 | mysql | db | 0 | 0 | 63 | mysql | general_log | 0 | 0 | 64 | performance_schema | events_stages_summary_by_account_by_event_name | 0 | 0 | 65 | performance_schema | variables_by_thread | 0 | 0 | 66 | book | user_book | 0 | 0 | 67 | performance_schema | events_stages_history | 0 | 0 | 68 | bigdata | dept | 0 | 0 | 69 | performance_schema | socket_instances | 0 | 0 | 70 | performance_schema | table_lock_waits_summary_by_table | 0 | 0 | 71 | mysql | time_zone | 0 | 0 | 72 | performance_schema | events_statements_summary_by_thread_by_event_name | 0 | 0 | 73 | performance_schema | users | 0 | 0 | 74 | performance_schema | setup_timers | 0 | 0 | 75 | performance_schema | memory_summary_by_host_by_event_name | 0 | 0 | 76 | performance_schema | setup_objects | 0 | 0 | 77 | performance_schema | host_cache | 0 | 0 | 78 | performance_schema | status_by_account | 0 | 0 | 79 | mysql | proxies_priv | 0 | 0 | 80 | performance_schema | memory_summary_by_account_by_event_name | 0 | 0 | 81 | performance_schema | accounts | 0 | 0 | 82 | performance_schema | replication_group_members | 0 | 0 | 83 | mysql | tables_priv | 0 | 0 | 84 | performance_schema | events_stages_summary_by_host_by_event_name | 0 | 0 | 85 | performance_schema | events_statements_current | 0 | 0 | 86 | mysql | proc | 0 | 0 | 87 | performance_schema | events_waits_summary_by_instance | 0 | 0 | 88 | performance_schema | events_statements_summary_by_host_by_event_name | 0 | 0 | 89 | performance_schema | memory_summary_by_user_by_event_name | 0 | 0 | 90 | performance_schema | events_transactions_history | 0 | 0 | 91 | mysql | event | 0 | 0 | 92 | performance_schema | status_by_host | 0 | 0 | 93 | performance_schema | setup_actors | 0 | 0 | 94 | performance_schema | threads | 0 | 0 | 95 | performance_schema | events_statements_summary_global_by_event_name | 0 | 0 | 96 | performance_schema | status_by_thread | 0 | 0 | 97 | performance_schema | file_summary_by_event_name | 0 | 0 | 98 | performance_schema | mutex_instances | 0 | 0 | 99 | performance_schema | table_handles | 0 | 0 | 100 | performance_schema | session_variables | 0 | 0 | 101 | bigdata | user | 1 | 0 | 102 | book | book_info | 0 | 0 | 103 | performance_schema | events_transactions_current | 0 | 0 | 104 | performance_schema | user_variables_by_thread | 0 | 0 | 105 | mysql | time_zone_transition | 0 | 0 | 106 | performance_schema | table_io_waits_summary_by_index_usage | 0 | 0 | 107 | performance_schema | events_transactions_history_long | 0 | 0 | 108 | performance_schema | memory_summary_global_by_event_name | 0 | 0 | 109 | performance_schema | events_statements_summary_by_digest | 0 | 0 | 110 | performance_schema | events_transactions_summary_by_host_by_event_name | 0 | 0 | 111 | performance_schema | events_waits_history | 0 | 0 | 112 | mysql | user | 0 | 0 | 113 | performance_schema | events_waits_summary_by_host_by_event_name | 0 | 0 | 114 | mysql | slow_log | 0 | 0 | 115 | performance_schema | file_summary_by_instance | 0 | 0 | 116 | mysql | server_cost | 0 | 0 | 117 | performance_schema | hosts | 0 | 0 | 118 | performance_schema | replication_applier_status | 0 | 0 | 119 | mysql | servers | 0 | 0 | 120 | performance_schema | events_stages_summary_by_thread_by_event_name | 0 | 0 | 121 +--------------------+------------------------------------------------------+--------+-------------+ 122 116 rows in set (0.01 sec) 123 124 mysql> show status like 'table%'; 125 +----------------------------+-------+ 126 | Variable_name | Value | 127 +----------------------------+-------+ 128 | Table_locks_immediate | 411 | 129 | Table_locks_waited | 0 | 130 | Table_open_cache_hits | 3 | 131 | Table_open_cache_misses | 1 | 132 | Table_open_cache_overflows | 0 | 133 +----------------------------+-------+ 134 5 rows in set (0.01 sec) 135 136 mysql>
16、行鎖的注意事項及使用情況分析:
1)、行鎖的注意事項,如果沒有索引,則行鎖會轉為表鎖。如果索引列發生了類型轉換,則索引失效。比如整數轉換為字符串類型,導致索引失效,會導致行鎖升級為表鎖。
2)、行鎖的一種特殊情況,間隙鎖,值在范圍內,但卻不存在。行鎖如果有where則實際加鎖的范圍就是where后面的范圍,不是數據表中保存的實際的值。
3)、行鎖的缺點比表鎖性能損耗大,優點是並發能力強,效率高。InnoDB默認采用的是行鎖。因此建議高並發采用InnoDB,否則使用MyISAM存儲引擎。
17、行鎖分析 show status like '%innodb_row_lock%';
1)、Innodb_row_lock_current_waits代表了當前正在等待鎖的數量。
2)、Innodb_row_lock_time代表了等待的總時長,從系統啟動到現在一共等待的時間。
3)、Innodb_row_lock_time_avg代表了平均等待時長,從系統啟動到現在平均等待的時間。
4)、Innodb_row_lock_time_max代表了最大等待時長,從系統啟動到現在最大一次等待的時間。
5)、Innodb_row_lock_waits代表了等待次數,從系統啟動到現在一共等待的次數。
1 mysql> show status like '%innodb_row_lock%'; 2 +-------------------------------+-------+ 3 | Variable_name | Value | 4 +-------------------------------+-------+ 5 | Innodb_row_lock_current_waits | 0 | 6 | Innodb_row_lock_time | 0 | 7 | Innodb_row_lock_time_avg | 0 | 8 | Innodb_row_lock_time_max | 0 | 9 | Innodb_row_lock_waits | 0 | 10 +-------------------------------+-------+ 11 5 rows in set (0.00 sec) 12 13 mysql>
將Mysql的自動提交關閉的三種方式,第一種方式set autocommit=0;第二種方式start transaction;第三種方式begin;通過for update對query查詢語句進行加鎖。