MySQL總結
本文主要涉及SQL/">MySQL核心元件、查詢過程、索引等原理,另外還涉及一些不常用但較重要的命令。除此之外,一些運維的理論和命令也有提及。
組成原理
主要介紹MySQL的核心元件,以及查詢執行過程。
元件
直接上圖
查詢過程
- 客戶端傳送一條查詢給伺服器;
- 伺服器先會檢查查詢快取,如果命中了快取,則立即返回儲存在快取中的結果。否則進入下一階段;
- 伺服器端進行SQL解析、預處理,再由優化器生成優化後對應的執行計劃;
- 根據優化器生成的執行計劃,呼叫儲存引擎的API來執行查詢;
- 將結果返回給客戶端。
儲存引擎
常用MySql儲存引擎比較,這裡重點講MyISAM和InnoDB。
指標 | MyISAM | InnoDB |
---|---|---|
事務 | 不支援 | 支援 |
讀寫效率 | 高 | 低 |
索引 | 支援全文索引 | 不支援全文索引 |
外來鍵 | 不支援 | 支援 |
鎖 | 表鎖 | 行鎖 |
檔案儲存形式 | .MYD .MYI *.FRM | *.FRM(預設為共享表空間,可修改) |
適用場景 | 大量select語句 | 大量update語句 |
刪除表後資料檔案是否存在 | 自動清除 | 不自動清除 |
鎖
三種類型
表級鎖 行級鎖 頁面鎖
兩種模式
共享鎖 排它鎖
索引
索引
: 是一種用來實現MySQL高效獲取資料的資料結構。在某個欄位上建索引, 就是讓MySQL對該欄位以索引這種資料結構來儲存, 然後查詢的時候就有對應的查詢演算法。
InnoDB使用 B+Tree
, B+Tree中的B是指balance, 意為平衡。需要注意的是, B+樹索引並不能找到一個給定鍵值的具體行, 它找到的只是被查詢資料行所在的頁, 接著資料庫會把頁讀入到記憶體, 再在記憶體中進行查詢, 最後得到要查詢的資料。
演算法介紹
平衡二叉樹
- 可以是空樹
- 如果不是空樹,任何一個結點的左子樹與右子樹都是平衡二叉樹,並且高度之差的絕對值不超過1
B-樹
- B-樹是一種多路自平衡的搜尋樹, 它類似普通的平衡二叉樹,不同的一點是B-樹允許每個節點有更多的子節點。
B+樹
- 所有關鍵字儲存在葉子節點出現, 內部節點(非葉子節點並不儲存真正的 data)
- 為所有葉子結點增加了一個鏈指標
索引型別
普通索引 唯一索引 主鍵
操作命令
- 建立索引
mysql> create index index1 on t_table(name); Query OK, 2 rows affected (0.00 sec) Records: 2Duplicates: 0Warnings: 0 mysql> alter table t_table add index index2 (grade); Query OK, 2 rows affected (0.00 sec) Records: 2Duplicates: 0Warnings: 0
- 檢視索引
mysql> show index from t_table; +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | t_table |1 | index1|1 | name| A|NULL |NULL | NULL| YES| BTREE||| | t_table |1 | index2|1 | grade| A|NULL |NULL | NULL| YES| BTREE||| +---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 2 rows in set (0.00 sec)
- 刪除索引
mysql> alter table t_table drop index index1; Query OK, 2 rows affected (0.00 sec) Records: 2Duplicates: 0Warnings: 0 mysql> drop index index2 on t_table; Query OK, 2 rows affected (0.01 sec) Records: 2Duplicates: 0Warnings: 0
SQL語句
SQL語句可以劃分為三個類別:
-
DDL
(Data Definition Languages)語句資料定義語言,這些語句定義了不同的資料段、 資料庫、表、列、索引等資料庫物件的定義。常用的語句關鍵字主要包括 create、drop、alter 等。
-
DML
(Data Manipulation Language)語句資料操縱語句,用於新增、刪除、更新和查詢資料庫記錄,並檢查資料完整性,常用的語句關鍵字主要包括 insert、delete、update 和 select 等。
-
DCL
(Data Control Language)語句資料控制語句,用於控制不同資料段直接的許可和 訪問級別的語句。這些語句定義了資料庫、表、欄位、使用者的訪問許可權和安全級別。主要的語句關鍵字包括 grant、revoke 等。
主從複製
基本流程
- slave端的IO執行緒連線上master端,並請求從指定binlog日誌檔案的指定pos節點位置(或者從最開始的日誌)開始複製之後的日誌內容。
- master端在接收到來自slave端的IO執行緒請求後,通知負責複製程序的IO執行緒,根據slave端IO執行緒的請求資訊,讀取指定binlog日誌指定pos節點位置之後的日誌資訊,然後返回給slave端的IO執行緒。該返回資訊中除了binlog日誌所包含的資訊之外,還包括本次返回的資訊在master端的binlog檔名以及在該binlog日誌中的pos節點位置。
- slave端的IO執行緒在接收到master端IO返回的資訊後,將接收到的binlog日誌內容依次寫入到slave端的relaylog檔案(mysql-relay-bin.xxxxxx)的最末端,並將讀取到的master端的binlog檔名和pos節點位置記錄到master-info(該檔案存在slave端)檔案中,以便在下一次讀取的時候能夠清楚的告訴master “我需要從哪個binlog檔案的哪個pos節點位置開始,請把此節點以後的日誌內容發給我”。
- slave端的SQL執行緒在檢測到relaylog檔案中新增內容後,會馬上解析該log檔案中的內容。然後還原成在master端真實執行的那些SQL語句,並在自身按順序依次執行這些SQL語句。這樣,實際上就是在master端和slave端執行了同樣的SQL語句,所以master端和slave端的資料是完全一樣的。
配置流程
- 在master庫執行
mysql> flush tables with read lock; Query OK, 0 rows affected (0.00 sec) mysql> show master status; +------------------+----------+--------------+------------------+ | File| Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000005 |107 ||| +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
[root@master ~]# mysqldump -uroot -p rep > /usr/local/mysql/rep.sql
mysql> unlock tables; Query OK, 0 rows affected (0.00 sec)
- 在slave庫執行
mysql < /usr/local/mysql/rep.sql
[root@slave ~]# vim /etc/my.cnf server-id=2// 設定server-id,不可重複 log-bin=mysql-bin// 開啟二進位制日誌,用於鏈式複製的情況下,即這臺伺服器如果需要作為其他從伺服器的主伺服器,則需要開啟這個選項 read_only = 1// 設定為只讀 relay_log = mysql-relay-bin//配置中繼日誌 log_slave_updates = 1// 表示slave將複製事件寫進自己的二進位制日誌
mysql> change master to -> master_host='192.168.30.110', -> master_user='rep', -> master_password='123456', -> master_log_file='mysql-bin.000005', -> master_log_pos=107; Query OK, 0 rows affected (0.06 sec) mysql> start slave; Query OK, 0 rows affected (0.03 sec)
常用操作
幫助命令
檢視系統時間
mysql> select now(); +---------------------+ | now()| +---------------------+ | 2018-09-21 08:16:48 | +---------------------+ 1 row in set (0.00 sec) mysql> select current_time; +--------------+ | current_time | +--------------+ | 08:17:02| +--------------+ 1 row in set (0.00 sec)
建立表
mysql> create table t_table(id int(11), -> name varchar(20), -> grade float ); Query OK, 0 rows affected (0.02 sec)
查詢表結構
mysql> describe t_table; +-------+-------------+------+-----+---------+-------+ | Field | Type| Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id| int(11)| YES|| NULL|| | name| varchar(20) | YES|| NULL|| | grade | float| YES|| NULL|| +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.02 sec)
查詢表建立語句
mysql> show create table t_table; +---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table| +---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | t_table | CREATE TABLE `t_table` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, `grade` float DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 | +---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> show create table t_table\G; *************************** 1. row *************************** Table: t_table Create Table: CREATE TABLE `t_table` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, `grade` float DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec) ERROR: No query specified
插入部分資料
mysql> insert into t_table(id,name) values(1,"henry"); Query OK, 1 row affected (0.01 sec) mysql> select * from t_table; +------+-------+-------+ | id| name| grade | +------+-------+-------+ |1 | henry |NULL | +------+-------+-------+ 1 row in set (0.00 sec)
插入完整資料
mysql> insert into t_table values(2,"cc", 3.30); Query OK, 1 row affected (0.00 sec) mysql> select * from t_table; +------+-------+-------+ | id| name| grade | +------+-------+-------+ |1 | henry |NULL | |2 | cc|3.3 | +------+-------+-------+ 2 rows in set (0.00 sec)
更新資料
mysql> update t_table set grade=1.10 where id=1; Query OK, 1 row affected (0.01 sec) Rows matched: 1Changed: 1Warnings: 0 mysql> select * from t_table; +------+-------+-------+ | id| name| grade | +------+-------+-------+ |1 | henry |1.1 | |2 | cc|3.3 | +------+-------+-------+ 2 rows in set (0.00 sec)
清空表
mysql> select * from table2; +------+------+ | id| xx| +------+------+ |1 | 323| +------+------+ 1 row in set (0.00 sec) mysql> truncate table table2; Query OK, 0 rows affected (0.01 sec) mysql> select * from table2; Empty set (0.00 sec)
查詢狀態
mysql> status; -------------- mysqlVer 14.14 Distrib 5.7.23, for Linux (x86_64) usingEditLine wrapper Connection id:2 Current database:test Current user:root@localhost SSL:Not in use Current pager:stdout Using outfile:'' Using delimiter:; Server version:5.7.23 MySQL Community Server (GPL) Protocol version:10 Connection:Localhost via UNIX socket Server characterset:latin1 Dbcharacterset:latin1 Client characterset:latin1 Conn.characterset:latin1 UNIX socket:/var/run/mysqld/mysqld.sock Uptime:1 hour 36 min 12 sec Threads: 1Questions: 48Slow queries: 0Opens: 108Flush tables: 1Open tables: 101Queries per second avg: 0.008 --------------
修改儲存引擎
mysql> alter table t_table engine=myisam; Query OK, 2 rows affected (0.01 sec) Records: 2Duplicates: 0Warnings: 0 mysql> show create table t_table; +---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table| +---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | t_table | CREATE TABLE `t_table` ( `id` int(11) DEFAULT NULL, `name` varchar(20) DEFAULT NULL, `grade` float DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 | +---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
修改慢查詢
mysql> show variables like '%slow%'; +---------------------------+--------------------------------------+ | Variable_name| Value| +---------------------------+--------------------------------------+ | log_slow_admin_statements | OFF| | log_slow_slave_statements | OFF| | slow_launch_time| 2| | slow_query_log| OFF| | slow_query_log_file| /var/lib/mysql/56bd89bc82a8-slow.log | +---------------------------+--------------------------------------+ 5 rows in set (0.01 sec) mysql> set global slow_query_log=ON; Query OK, 0 rows affected (0.01 sec) mysql> show variablesshow master status; like '%slow_query_log%'; +---------------------+--------------------------------------+ | Variable_name| Value| +---------------------+--------------------------------------+ | slow_query_log| ON| | slow_query_log_file | /var/lib/mysql/56bd89bc82a8-slow.log | +---------------------+--------------------------------------+ mysql> select sleep(10); +-----------+ | sleep(10) | +-----------+ |0 | +-----------+ 1 row in set (10.00 sec) mysql> exit Bye root@56bd89bc82a8:/# mysqldumpslow /var/lib/mysql/56bd89bc82a8-slow.log Reading mysql slow query log from /var/lib/mysql/56bd89bc82a8-slow.log Count: 1Time=0.00s (0s)Lock=0.00s (0s)Rows=0.0 (0), 0users@0hosts mysqld, Version: N.N.N (MySQL Community Server (GPL)). started with: # Time: N-N-21T13:N:N.266357Z # User@Host: root[root] @ localhost []Id:N # Query_time: N.NLock_time: N.N Rows_sent: NRows_examined: N use test; SET timestamp=N; select sleep(N)
檢視程序
mysql> show full processlist\G *************************** 1. row *************************** Id: 2 User: root Host: localhost db: test Command: Query Time: 0 State: starting Info: show full processlist 1 row in set (0.00 sec)
效能分析
mysql> explain select * from t_table; +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+ | id | select_type | table| partitions | type | possible_keys | key| key_len | ref| rows | filtered | Extra | +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+ |1 | SIMPLE| t_table | NULL| ALL| NULL| NULL | NULL| NULL |2 |100.00 | NULL| +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
安全加固
mysql_secure_installation
主要包含以下操作:
- 為root使用者設定密碼
- 刪除匿名賬號
- 取消root使用者遠端登入
- 刪除test庫和對test庫的訪問許可權
- 重新整理授權表使修改生效