學習 MySQL 需要知道的 28 個小技巧

數據分析那些事
39 min readAug 22, 2022

--

前言

隨著資訊科技的不斷髮展以及網際網路行業的高速增長,作為開源資料庫的MySQL得到了廣泛的應用和發展。目前MySQL已成為關係型資料庫領域中非常重要的一員。

無論是運維、開發、測試,還是架構師,資料庫技術都是一個 必備加薪神器,那麼,一直說學習資料庫、學 MySQL,到底是要學習它的哪些東西呢?

一、如何快速掌握 MySQL?

培養興趣

興趣是最好的老師,不論學習什麼知識,興趣都可以極大地提高學習效率。不管學習 MySQL5.7 還是 MySQL8.0 都不例外!

夯實 SQL 基礎

計算機領域的技術非常強調基礎,剛開始學習可能還認識不到這一點。隨著技術應用的深 入,只有有著紮實的基礎功底,才能在技術的道路上走得更快、更遠。對於 MySQL 的學習來說, SQL 語句 是其中最為基礎的部分,很多操作都是透過 SQL 語句來實現的。所以在學習的過程中, 讀者要多編寫 SQL 語句,對於同一個功能,使用不同的實現語句來完成,從而深刻理解其不同之處。

及時學習新知識

正確、有效地利用搜索引擎,可以搜尋到很多關於 MySQL 的相關知識。同時,參考別 人解決問題的思路,也可以吸取別人的經驗,及時獲取最新的技術資料。

多實踐操作

資料庫系統具有極強的操作性,需要多動手上機操作。在實際操作的過程中才能發現問題, 並思考解決問題的方法和思路,只有這樣才能提高實戰的操作能力。

二、技巧分享

下面分享學習 MySQL 的 28 個不得不知道的小技巧!

1、MySQL 中如何使用特殊字元?

諸如單引號 ‘ ,雙引號 “,反斜線 \ 等符號,這些符號在 MySQL 中不能直接輸入使用,否則會產生意料之外的結果。

舉例:

假設 Lucifer 表中需要存入一行記錄,值為 lucifer’s dog,其中的單引號 ‘ 號,如果不做轉義,則無法成功執行:

mysql> create table lucifer (id int,name char(100));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into lucifer values (1,'lucifer's dog');
'>
'> mysql>

^C
mysql>

在 MySQL 中,這些特殊字元稱為跳脫字元,在輸入時需要以反斜線符號 \ 開頭,所以在使用單引號和雙引號時應分別輸入 \' 或者 \",輸入反斜線時應該輸入 \\,其他特殊字元還有回車符 \r,換行符 \n,製表符 \tab,退格符 \b 等。

mysql> create table lucifer (id int,name char(100));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into lucifer values (1,'lucifer\'s dog');
Query OK, 1 row affected (0.00 sec)

mysql> select * from lucifer;
+------+---------------+
| id | name |
+------+---------------+
| 1 | lucifer's dog |
+------+---------------+
1 row in set (0.00 sec)
mysql>

📢 注意: 在向資料庫中插入這些特殊字元時,一定要進行轉義處理。

2、MySQL 中可以儲存檔案嗎?

答案當然是可以的!

MySQL 中的 BLOB 和 TEXT 欄位型別可以儲存資料量較大的檔案,可以使用這些資料型別 儲存影象、聲音或者是大容量的文字內容,例如網頁或者文件。

mysql> create table view(id int unsigned NOT NULL AUTO_INCREMENT, catid int,title varchar(256),picture MEDIUMBLOB, content TEXT,PRIMARY KEY (id));
Query OK, 0 rows affected (0.03 sec)

mysql> show fields from view;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| catid | int | YES | | NULL | |
| title | varchar(256) | YES | | NULL | |
| picture | mediumblob | YES | | NULL | |
| content | text | YES | | NULL | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

雖然使用 BLOB 或者 TEXT 可 以儲存大容量的資料,但是對這些欄位的處理會降低資料庫的效能。

📢 注意: 如果並非必要,可以選擇只儲存檔案的路徑。

3、MySQL 中如何執行區分大小寫的字串比較?

MySQL 是 不區分大小寫 的,因此字串比較函式也不區分大小寫。

mysql> select 'TRUE' from dual where 'DOG' = 'dog';
+------+
| TRUE |
+------+
| TRUE |
+------+
1 row in set (0.00 sec)

如果想執行區分大小寫的比較,可以在字串前面新增 BINARY 關鍵字。

mysql> select 'TRUE' from dual where BINARY'DOG' = 'dog';
Empty set (0.00 sec)

mysql>

例如預設情況下,’DOG‘=’dog‘ 返回結果為 TRUE,如果使用 BINARY 關鍵字,BINARY’DOG’=‘dog’ 結果為 FALSE,在區分大小寫的情況下,’DOG’ 與 ’dog’ 並不相同。

4、如何從日期時間值中獲取年、月、日等部分日期或時間值?

MySQL 中,日期時間值以字串形式儲存在資料表中,因此可以使用字串函式分別擷取日期時間值的不同部分。

mysql> create table lucifer(date date);
Query OK, 0 rows affected (0.04 sec)

mysql> show fields from lucifer;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| date | date | YES | | NULL | |
+-------+------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> insert into lucifer values (now());
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from lucifer;
+------------+
| date |
+------------+
| 2021-11-25 |
+------------+
1 row in set (0.00 sec)

例如某個名稱為 date 的欄位有值 2021–11–25,如果只需要獲得年值,可以輸入 LEFT(date, 4),這樣就獲得了字串左邊開始長度為 4 的子字串,即 YEAR 部分的值;

mysql> select LEFT(date, 4) from lucifer;
+---------------+
| LEFT(date, 4) |
+---------------+
| 2021 |
+---------------+
1 row in set (0.00 sec)

如果要獲取月份值,可以輸入 MID(date,6,2),字串第 6 個字元開始,長度為 2 的子字串正好為 date 中的月份值。同理,讀者可以根據其他日期和時間的位置,計算並獲取相應的值。

mysql> select MID(date,6,2) from lucifer;
+---------------+
| MID(date,6,2) |
+---------------+
| 11 |
+---------------+
1 row in set (0.00 sec)

5、如何改變預設的字符集?

CONVERT() 函式改變指定字串的預設字符集!

MySQL 的安裝和配置過程中,其中的一個步驟是可以選擇 MySQL 的預設字符集。但是,如果只改變字符集,沒有必要把配置過程重新執行一遍,在這裡,一個簡單的方式是 修改配置檔案

讀者可以在修改字符集時使用 SHOW VARIABLES LIKE ‘character_set_%’; 或者 status 命令檢視當前字符集,以進行對比。

mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | utf8mb3 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> status
--------------
mysql Ver 8.0.26-0ubuntu0.21.04.3 for Linux on aarch64 ((Ubuntu))

Connection id: 10
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.26-0ubuntu0.21.04.3 (Ubuntu)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: latin1
Conn. characterset: latin1
UNIX socket: /var/run/mysqld/mysqld.sock
Binary data as: Hexadecimal
Uptime: 36 min 55 sec

Threads: 2 Questions: 325 Slow queries: 0 Opens: 181 Flush tables: 3 Open tables: 69 Queries per second avg: 0.146
--------------

mysql>

MySQL 配置檔名稱為 my.cnf,該檔案在 MySQL 的安裝目錄下面。修改配置檔案中的 default-character-setcharacter-set-server 引數值,將其改為想要的字符集名稱,如 gbk、gb2312、latinl 等,修改完之後重新啟動 MySQL 服務,即可生效。

## 找到 my.cnf 位置
root@modb:~# find /etc -iname my.cnf -print
/etc/alternatives/my.cnf
/etc/mysql/my.cnf

## 修改字符集
在[client ]下面加入
default-character-set=utf8
在[ mysqld ] 下面加
character_set_server=utf8

## 重启 mysql 生效
service mysql restart

此時,登入 MySQL 後使用 SHOW VARIABLES LIKE 'character_set_%'; 或者 status 命令檢視修改結果!

6、DISTINCT 可以應用於所有的列嗎?

查詢結果中,如果需要對列進行降序排序,可以使用DESC,這個關鍵字只能對其前面的列 進行降序排列。

mysql> select * from lucifer;
+------+----------+
| id | name |
+------+----------+
| 1 | lucifer |
| 2 | lucifer1 |
| 3 | lucifer2 |
+------+----------+
3 rows in set (0.00 sec)

mysql> select * from lucifer order by id desc;
+------+----------+
| id | name |
+------+----------+
| 3 | lucifer2 |
| 2 | lucifer1 |
| 1 | lucifer |
+------+----------+
3 rows in set (0.00 sec)

例如,要對多列都進行降序排序,必須要在每一列的列名後面加 DESC 關鍵字。

mysql> select * from lucifer order by id desc,name desc;
+------+----------+
| id | name |
+------+----------+
| 3 | lucifer2 |
| 2 | lucifer1 |
| 1 | lucifer |
+------+----------+
3 rows in set (0.00 sec)

DISTINCT 不同,DISTINCT 不能部分使用。換句話說,DISTINCT 關鍵字應用於所有列而不僅是它後面的第一個指定列。

例如,查詢 2 個欄位 sex,age,如果不同記錄的這 2 個欄位的組合值都不同,則所有記錄都會被查詢出來。

mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 20 |
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
| 1 | xiaowu | female | 21 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)

mysql> select distinct sex,age from lucifer;
+--------+------+
| sex | age |
+--------+------+
| male | 20 |
| female | 21 |
+--------+------+
2 rows in set (0.00 sec)

mysql>

7、ORDER BY 可以和 LIMIT 混合使用嗎?

在使用 ORDER BY 子句時,應保證其位於 FROM 子句之後,如果使用 LIMIT,則必須位於 ORDER BY 之後,如果子句順序不正確,MySQL 將產生錯誤訊息。

✅ 正確用法:

mysql> select * from lucifer order by age desc limit 2,4;
+------+--------+--------+------+
| id | name | sex | age |
+------+--------+--------+------+
| 1 | xiaowu | female | 21 |
| 1 | xiaoli | male | 20 |
+------+--------+--------+------+
2 rows in set (0.00 sec)

❎ 錯誤用法:

mysql> select * from lucifer limit 2,4 order by age desc;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order by age desc' at line 1
mysql>

8、什麼時候使用引號?

在查詢的時候,會看到在 WHERE 子句中使用條件,有的值加上了單引號,而有的值未加。

mysql> select * from lucifer where sex = 'female';
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
| 1 | xiaowu | female | 21 |
+------+-----------+--------+------+
3 rows in set (0.00 sec)

mysql>

單引號用來限定字串,如果將值與字串型別列進行比較,則需要限定引號;而用來與數值進行比較則不需要用引號。

mysql> select * from lucifer where age = 20;
+------+--------+------+------+
| id | name | sex | age |
+------+--------+------+------+
| 1 | xiaoli | male | 20 |
+------+--------+------+------+
1 row in set (0.00 sec)

mysql>

9、在 WHERE子句中 AND 和 OR 必須使用圓括號嗎?

任何時候使用具有 ANDOR 運算子的 WHERE 子句,都應該使用圓括號明確操作順序。

mysql> select * from lucifer where (age = 20 or sex = 'female') and name != 'xiaowu';
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 20 |
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
+------+-----------+--------+------+
mysql> 3 rows in set (0.00 sec)

如果條件較多,即使能確定計算次序,預設的計算次序也可能會使 SQL 語句不易理解,因此使 用括號明確運算子的次序,是一個好的習慣。

10、更新或者刪除表時必須指定 WHERE子 句嗎?

個人建議所有的 UPDATE 和 DELETE 語句全都在 WHERE 子句中指定條件。

mysql> update lucifer set age = 22 where name = 'xiaoliu';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from lucifer where name = 'xiaoliu';
+------+---------+--------+------+
| id | name | sex | age |
+------+---------+--------+------+
| 1 | xiaoliu | female | 22 |
+------+---------+--------+------+
1 row in set (0.00 sec)

mysql>

如果省略 WHERE 子句,則 UPDATE 或 DELETE 將被應用到表中所有的行。

mysql> update lucifer set age = 22;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 4 Changed: 3 Warnings: 0

mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)

mysql>

因此,除非確實打算更新或者刪除所有記錄,否則要注意使用不帶 WHERE 子句的 UPDATE 或 DELETE 語句。

📢 注意: 建議在對錶進行更新和刪除操作之前,使用 SELECT 語句確認需要刪除的記錄,以免造成無法挽回的結果。

11、索引對資料庫效能如此重要,應該如何使用它?

索引的優點:

透過建立唯一索引可以保證資料庫表中每一行資料的唯一性。
可以給所有的 MySQL 列型別設定索引。
可以大大加快資料的查詢速度,這是使用索引最主要的原因。
在實現資料的參考完整性方面可以加速表與表之間的連線。
在使用分組和排序子句進行資料查詢時也可以顯著減少查詢中分組和排序的時間。

缺點:

建立和維護索引組要耗費時間,並且隨著資料量的增加所耗費的時間也會增加。
索引需要佔磁碟空間,除了資料表佔資料空間以外,每一個索引還要佔一定的物理空間。如果有大量的索引,索引檔案可能比資料檔案更快達到最大檔案尺寸。
當對錶中的資料進行增加、刪除和修改的時候,索引也要動態維護,這樣就降低了資料的維護速度。

使用索引時,需要綜合考慮索引的優點和缺點。

為資料庫選擇正確的索引是一項複雜的任務。如果索引列較少,則需要的磁碟空間和維護開銷 都較少。如果在一個大表上建立了多種組合索引,索引檔案也會膨脹很快。

而另一方面,索引較多 可覆蓋更多的查詢。可能需要試驗若干不同的設計,才能找到最有效的索引。可以新增、修改和刪 除索引而不影響資料庫架構或應用程式設計。

因此,應嘗試多個不同的索引從而建立最優的索引。

12、儘量使用短索引(字首索引)

對字串型別的欄位進行索引,如果可能應該指定一個字首長度。

例如,如果有一個 CHAR(255) 的列,如果在前 10 個或 30 個字元內,多數值是惟一的,則不需要對整個列進行索引。

mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)

mysql> create index idx_lucifer_name on lucifer (name(4));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> show index from lucifer;
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| lucifer | 1 | idx_lucifer_name | 1 | name | A | 1 | 4 | NULL | YES | BTREE | | | YES | NULL |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.01 sec)

mysql>

短索引不僅可以提高查詢速度而且可以節省磁碟空間、減少 I/O 操作。

13、MySQL 儲存過程和函式有什麼區別?

在本質上它們都是儲存程式。

函式:

只能透過 return 語句返回單個值或者表物件;
限制比較多,不能用臨時表,只能用表變數,還有一些函式都不可用等等;
可以嵌入在 SQL 語句中使用,可以在 SELECT 語句中作為查詢語句的一個部分呼叫;

儲存過程:

不允許執行 return,但是可以透過 out 引數返回多個值;
限制相對就比較少;
一般是作為一個獨立的部分來執行;

14、儲存過程中的內容可以改變嗎?

不可以!

目前,MySQL 還不提供對已存在的儲存過程程式碼的修改,如果必須要修改儲存過程,必須使用 DROP 語句刪除之後,再重新編寫程式碼,或者建立一個新的儲存過程。

不得不說,這方面還是 Oracle 做的比較好。

15、儲存過程中可以呼叫其他儲存過程嗎?

可以!

儲存過程包含使用者定義的 SQL 語句集合,可以使用 CALL 語句呼叫儲存過程,當然在儲存過程中也可以使用 CALL 語句呼叫其他儲存過程,但是不能使用 DROP 語句刪除其他儲存過程。

16、儲存過程的引數不要與資料表中的欄位名相同。

在定義儲存過程引數列表時,應注意把引數名與資料庫表中的欄位名區別開來,否則將出 現無法預期的結果。

17、儲存過程的引數可以使用中文嗎?

一般情況下,可能會出現儲存過程中傳入中文引數的情況,例如某個儲存過程根據使用者的 名字查詢該使用者的資訊,傳入的引數值可能是中文。這時需要在定義儲存過程的時候,在後面加 上 character set gbk,不然呼叫儲存過程使用中文引數會出錯,比如定義 userInfo 儲存過程,程式碼 如下:

CREATE PROCEDURE useInfo(IN u_name VARCHAR(50) character set gbk, OUT u_age INT)

18、MySQL 中檢視和表的區別以及聯絡是什麼?

兩者的區別:

檢視是已經編譯好的 SQL 語句,是基於 SQL 語句的結果集的視覺化的表,而表不是;
檢視沒有實際的物理記錄,而基本表有;
表是內容,檢視是視窗;
表佔用物理空間而檢視不佔用物理空間,檢視只是邏輯概念的存在,表可以及時對它進行修改,但檢視只能用建立的語句來修改;
檢視是檢視資料表的一種方法,可以查詢資料表中某些欄位構成的資料,只是一些SQL 語句的集合。從安全的角度來說,檢視可以防止使用者接觸資料表,因而使用者不知道表結構;
表屬於全域性模式中的表,是實表;檢視屬於區域性模式的表,是虛表;
檢視的建立和刪除隻影響檢視本身,不影響對應的基本表;

兩者的聯絡:

檢視(view)是在基本表之上建立的表,它的結構(即所定義的列)和內容(即所有記錄) 都來自基本表,它依據基本表存在而存在。

一個檢視可以對應一個基本表,也可以對應多個基本表。

檢視是基本表的抽象和在邏輯意義上建立的新關係。

19、使用觸發器時須特別注意!

在使用觸發器的時候需要注意,對於相同的表,相同的事件只能建立一個觸發器。

mysql> create trigger lucifer_tri before insert on lucifer for each row set NEW.id=NEW.id+1;
Query OK, 0 rows affected (0.01 sec)

mysql>
mysql>
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
| 1 | lucifer | male | 20 |
| 1 | lucifer | male | 20 |
+------+-----------+--------+------+
6 rows in set (0.00 sec)

mysql> insert into lucifer values(1,'lucifer','male',20);
Query OK, 1 row affected (0.00 sec)

mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
| 1 | lucifer | male | 20 |
| 1 | lucifer | male | 20 |
| 2 | lucifer | male | 20 |
+------+-----------+--------+------+
7 rows in set (0.00 sec)

比如對錶 lucifer 建立了一個 BEFORE INSERT 觸發器,那麼如果對錶 lucifer 再次建立一個 BEFORE INSERT 觸發器,MySQL 將會報錯,此時,只可以在表 lucifer 上建立 AFTER INSERT 或者 BEFORE UPDATE 型別的觸發器。

mysql> create trigger lucifer_tri before insert on lucifer for each row set NEW.id=NEW.id+1;
ERROR 1359 (HY000): Trigger already exists
mysql>

靈活的運用觸發器將為操作省去很多麻煩。

20、及時刪除不再需要的觸發器

觸發器定義之後,每次執行觸發事件,都會啟用觸發器並執行觸發器中的語句。

如果需求發生變化,而觸發器沒有進行相應的改變或者刪除,則觸發器仍然會執行舊的語句,從而會影響新的資料的完整性。

mysql> drop trigger lucifer_tri;
Query OK, 0 rows affected (0.03 sec)

mysql>

因此,要將不再使用的觸發器及時刪除。

21、應該使用哪種方法建立使用者?(3種方式)

建立使用者有 3 種方法:

使用 CREATE USER 語句建立使用者
在 mysql.user 表中新增使用者
使用 GRANT 語句建立使用者(僅限 MySQL 8 版本以下使用)

一般情況, 最好使用 GRANT 或者 CREATE USER 語句,而不要直接將使用者資訊插入 user 表,因為 user 表中儲存了全域性級別的許可權以及其他的賬戶資訊,如果意外破壞了 user 表中的記錄,則可能會對 MySQL 伺服器造成很大影響。

-- 使用 CREATE USER 语句创建用户
mysql> create user 'lucifer'@'localhost' identified by 'lucifer';
Query OK, 0 rows affected (0.01 sec)

mysql>

-- 在 mysql.user 表中添加用户
mysql> select MD5('lucifer');
+----------------------------------+
| MD5('lucifer') |
+----------------------------------+
| cae33a0264ead2ddfbc3ea113da66790 |
+----------------------------------+
1 row in set (0.00 sec)

mysql>
mysql> INSERT INTO mysql.user(Host, User, authentication_string, ssl_cipher, ssuex509_i09_sr, x5ubject) VALUES ('lohoscalt',uci 'lfer MD5('1',lucifer'), '', '',; '')
Query OK, 1 row affected (0.01 sec)

mysql>

-- 使用 GRANT 语句创建用户
mysql> GRANT SELECT ON*.* TO 'lucifer2'@localhost IDENTIFIED BY 'lucifer';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY 'lucifer'' at line 1
mysql>

📢 注意: 由於測試使用的是 MySQL 8 版本,已經不支援 GRANT 直接建立使用者,5.7 版本依然是支援的。

22、mysqldump 備份的檔案只能在 MySQL 中使用嗎?

邏輯備份工具,適用於所有的儲存引擎,支援溫備、完全備份、部分備份、對於 InnoDB 儲存引擎支援熱備。

mysqldump 備份的文字檔案實際是資料庫的一個副本,使用該檔案不僅可以在 MySQL 中恢復資料庫,而且透過對該檔案的簡單修改,可以使用該檔案在 SQL Server 或者 Sybase 等其他資料庫中恢復資料庫。

root@modb:~# mysqldump -uroot -p hr > /root/hr.db
Enter password:
root@modb:~#
root@modb:~# ll hr.db
-rw-r--r-- 1 root root 25327 Nov 26 08:52 hr.db

這在某種程度上實現了資料庫之間的遷移。

23、如何選擇備份工具?

根據備份的方法(是否需要資料庫離線)可以將備份分為:

熱備(Hot Backup)
冷備(Cold Backup)
溫備(Warm Backup)

MySQL 中進行不同方式的備份還要考慮儲存引擎是否支援,如 MyISAM 不支援熱備,支援溫備和冷備。而 InnoDB 支援熱備、溫備和冷備。

一般情況下,我們需要備份的資料分為以下幾種:

表資料
二進位制日誌、InnoDB 事務日誌
程式碼(儲存過程、儲存函式、觸發器、事件排程器)
伺服器配置檔案

下面是幾種常用的備份工具:

mysqldump:邏輯備份工具,適用於所有的儲存引擎,支援溫備、完全備份、部分備份、對於 InnoDB 儲存引擎支援熱備。
cp、tar 等歸檔複製工具:物理備份工具,適用於所有的儲存引擎、冷備、完全備份、部分備份。
lvm2 snapshot:藉助檔案系統管理工具進行備份。
mysqlhotcopy:名不副實的一個工具,僅支援 MyISAM 儲存引擎。
xtrabackup:一款由 percona 提供的非常強大的 InnoDB/XtraDB 熱備工具,支援完全備份、增量備份。

直接複製資料檔案是最為直接、快速的備份方法,但缺點是基本上不能實現增量備份。備份時必須確保沒有使用這些表。如果在複製一個表的同時伺服器正在修改它,則複製無效。備份 檔案時,最好關閉伺服器,然後重新啟動伺服器。

24、平時應該開啟哪些日誌?

日誌既會影響 MySQL 的效能,又會佔用大量磁碟空間。因此,如果不必要,應儘可能少地 開啟日誌。

根據不同的使用環境,可以考慮開啟不同的日誌。

例如,在開發環境中最佳化查詢效率低的語句,可以開啟慢查詢日誌;

開啟慢查詢日誌: 可以讓MySQL記錄下查詢超過指定時間的語句,透過定位分析效能的瓶頸,才能更好的最佳化資料庫系統的效能。

-- 检查是否开启慢查询
mysql> show variables like 'slow_query%';
+---------------------+------------------------------+
| Variable_name | Value |
+---------------------+------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/modb-slow.log |
+---------------------+------------------------------+
2 rows in set (0.00 sec)

mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)

-- 开启慢查询日志
mysql> set global slow_query_log='ON';
Query OK, 0 rows affected (0.00 sec)

-- 设置查询超过10秒就记录
mysql> set global long_query_time=10;
Query OK, 0 rows affected (0.00 sec)

-- 再次检查是否开启
mysql> show variables like 'slow_query%';
mysql> +---------------------+------------------------------+
| Variable_name | Value |
+---------------------+------------------------------+
| slow_query_log | ON |
| slow_query_log_file | /var/lib/mysql/modb-slow.log |
+---------------------+------------------------------+
2 rows in set (0.00 sec)

如果需要記錄使用者的所有查詢操作,可以開啟通用查詢日誌;

mysql> show variables like 'general_log%';
+------------------+-------------------------+
| Variable_name | Value |
+------------------+-------------------------+
| general_log | OFF |
| general_log_file | /var/lib/mysql/modb.log |
+------------------+-------------------------+
2 rows in set (0.00 sec)

-- 开启通用查询日志
mysql> SET GLOBAL general_log=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'general_log%';
+------------------+-------------------------+
| Variable_name | Value |
+------------------+-------------------------+
| general_log | ON |
| general_log_file | /var/lib/mysql/modb.log |
+------------------+-------------------------+
2 rows in set (0.00 sec)

如果需要記錄資料的變更,可以開啟二進位制日誌;錯誤日誌是預設開啟的。

mysql> show variables like 'log_bin%';
+---------------------------------+-----------------------------+
| Variable_name | Value |
+---------------------------------+-----------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/binlog |
| log_bin_index | /var/lib/mysql/binlog.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
+---------------------------------+-----------------------------+
5 rows in set (0.00 sec)

mysql>

25、如何使用二進位制日誌?

二進位制日誌主要用來記錄資料變更。

如果需要記錄資料庫的變化,可以開啟二進位制日誌。基於二進位制日誌的特性,不僅可以用來進行資料恢復,還可用於資料複製。

root@modb:/var/lib/mysql# ls binlog*
binlog.000001 binlog.000002 binlog.index
root@modb:/var/lib/mysql# mysqlbinlog binlog.000001 | mysql -u root -p
Enter password:
root@modb:/var/lib/mysql#

在資料庫定期備份的 情況下,如果出現數據丟失,可以先用備份恢復大部分資料,然後使用二進位制日誌恢復最近備份後變更的資料。在雙機熱備情況下,可以使用 MySQL 的二進位制日誌記錄資料的變更,然後將變更部分複製到備份伺服器上。

26、如何使用慢查詢日誌?

慢查詢日誌主要用來記錄查詢時間較長的日誌。

在開發環境下,可以開啟慢查詢日誌來記錄查詢時間較長的查詢語句,然後對這些語句進行最佳化。

root@modb:/var/lib/mysql# cat /var/lib/mysql/modb-slow.log
/usr/sbin/mysqld, Version: 8.0.26-0ubuntu0.21.04.3 ((Ubuntu)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
root@modb:/var/lib/mysql#

透過配 long_query_time 的值,可以靈活地掌握不同程度的慢查詢語句。

27、是不是索引建立得越多越好?

合理的索引可以提高查詢的速度,但不是索引越多越好。

在執行插入語句的時候,MySQL 要為新插入的記錄建立索引。所以過多的索引會導致插入操作變慢。原則上是隻有查詢用的欄位才建立索引。

使用索引時,需要綜合考慮索引的優點和缺點。

28、如何使用查詢緩衝區?

查詢緩衝區可以提高查詢的速度,但是這種方式只適合查詢語句比較多、更新語句比較少 的情況。

預設情況下查詢緩衝區的大小為 0,也就是不可用。可以修改queiy_cache_size 以調整查詢緩衝區大小;修改 query_cache_type 以調整查詢緩衝區的型別。

my.cnf 中修改 query_cache_sizequery_cache_type 的值如下所示:

[mysqld]
query_cache_size= 512M
query_cache_type= 1
query_cache_type=1

表示開啟查詢緩衝區。

只有在查詢語句中包含 SQL_NO_CACHE 關鍵字時,才不會使用查詢緩衝區。可以使用FLUSH QUERY CACHE 語句來重新整理緩衝區,清理查詢緩衝區中的碎片。

文章來源:Lucifer三思而後行

文章連接:https://mp.weixin.qq.com/s/JqSpx-wanOu_bPHH9wDOJg

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

我是「數據分析那些事」。常年分享數據分析乾貨,不定期分享好用的職場技能工具。各位也可以關注我的Facebook,按讚我的臉書並私訊「10」,送你十週入門數據分析電子書唷!期待你與我互動起來~

文章推薦

餅圖變形記,肝了3000字,收藏就是學會!

MySQL必須掌握4種語言!

太實用了!4種方法教你輕鬆製作互動式儀表板!

跟資料打交道的人都得會的這8種資料模型,滿足工作中95%的需求

妙呀!一行Python程式碼

--

--

數據分析那些事
數據分析那些事

Written by 數據分析那些事

這是一個專注於數據分析職場的內容部落格,聚焦一批數據分析愛好者,在這裡,我會分享數據分析相關知識點推送、(工具/書籍)等推薦、職場心得、熱點資訊剖析以及資源大盤點,希望同樣熱愛數據的我們一同進步! 臉書會有更多互動喔:https://www.facebook.com/shujvfenxi/

No responses yet