12種mysql常見錯誤總結 +分析示例

前言

小夥伴們好,我是阿沐!最近呢,正籌備上雲工做,須要考慮到不少場景;好比mongo、mysql、redis、splinx等等遷移工做,這就涉及到版本兼容問題;在遷移以前,阿沐遷移了mysql到其餘容器中,發現遷移機器mysql版本號比較高5.7以上,就出現了sql語句兼容問題。因此趁機會整理了好久之前遇到的各類mysql常見問題跟掘金小夥伴們分享下。小夥伴們能夠收藏起來哦,遇到常規錯誤能夠快速查詢解決~~~mysql

一、localhost上的mysql沒法鏈接

報錯代碼:
ERROR 2003 (HY000):Can’t connect to MySQL server on 'localhost' (10061)
複製代碼
報錯緣由:
① 很明顯,localhost本機是存在的;可是它卻沒有提供mysql的服務供給使用

② 檢查磁盤空間是否還有剩餘可用空間,儘可能保持有足夠的磁盤空間可用

③ 查看mysql的負載能力,可能存在mysql的負載太高咱們鏈接不上;通常是看processlist來看下具體線程和鏈接數運行狀況:
       
       1show processlist只能列出當前100條,咱們能夠看到全部用戶的鏈接狀況
       
       mysql> show processlist;
        +----+-----------------+-----------+------+---------+-------+------------------------+------------------+
        | Id | User            | Host      | db   | Command | Time  | State                  | Info             |
        +----+-----------------+-----------+------+---------+-------+------------------------+------------------+
        |  4 | event_scheduler | localhost | NULL | Daemon  | 30404 | Waiting on empty queue | NULL             |
        | 14 | root            | localhost | NULL | Query   |     0 | starting               | show processlist |
        +----+-----------------+-----------+------+---------+-------+------------------------+------------------+
        2 rows in set (0.00 sec)
       
       2、查看所有的連接狀況
       
       mysql> show full processlist;
        +----+-----------------+-----------+------+---------+-------+------------------------+-----------------------+
        | Id | User            | Host      | db   | Command | Time  | State                  | Info                  |
        +----+-----------------+-----------+------+---------+-------+------------------------+-----------------------+
        |  4 | event_scheduler | localhost | NULL | Daemon  | 30527 | Waiting on empty queue | NULL                  |
        | 14 | root            | localhost | NULL | Query   |     0 | starting               | show full processlist |
        +----+-----------------+-----------+------+---------+-------+------------------------+-----------------------+
        2 rows in set (0.00 sec)
        
# 注意,針對以上查看結果進行詳細字段說明:

① Id 當用戶登陸mysql時,系統會爲用戶分配一個"connection_id",可使用函數connection_id()來查看:
    mysql> select connection_id();
    +-----------------+
    | connection_id() |
    +-----------------+
    |              14 |  -- 系統分配的id爲14
    +-----------------+
    1 row in set (0.01 sec)

② User 展現當前連接用戶

③ Host 鏈接mysql的ip地址;可查到來源端口,同時能夠跟蹤出現問題語句的用戶

④ db   鏈接數據庫的名稱

⑤ Command 當前連接執行的命令;query(查詢)、sleep(休眠)、connect(鏈接)、daemon(守護進程)

⑥ Time  當前鏈接持續時長,單位時間是秒

⑦ State 展現當前鏈接的sql語句狀態

⑧ Info 展現sql語句,對用來判斷sql語句是否有問題很重要

複製代碼
問題解決方案:
① mysql未啓動,則啓動便可:

    mac端:brew services start mysql   mysql.server start 
    centos端: systemctl start mysqld.service    service mysql start
    其餘:找到執行文件根目錄執行 啓動也ok
複製代碼

二、localhost/IP地址鏈接不上

報錯代碼:
~ mysql -uroot -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
複製代碼
報錯緣由:
① 概述:用戶root訪問localhost/IP被拒絕訪問

② 通常是數據庫的用戶名或者密碼跟服務器上mysql設置的不一致,致使匹配失敗

複製代碼
問題解決方案:
# 注意解決步驟:

① 查看mysql配置文件

② 查看 mysql 配置文件加載順序

③ 修改配置文件跳過權限驗證(skip-grant-tables)

④ 登陸mysql客戶端修改密碼

複製代碼
注意mac版本方案:
① 查看mysql運行狀況,看看在哪裏
➜  ~ ps aux | grep mysql   -- 查看mysql的運行進程 能夠看到啓動地址
amu       15262   0.0  4.9  4899000 407680   ??  S     1:14下午   0:01.18 /usr/local/opt/mysql/bin/mysqld 
--basedir=/usr/local/opt/mysql 
--datadir=/usr/local/var/mysql 
--plugin-dir=/usr/local/opt/mysql/lib/plugin 
--log-error=liyangyang.local.err 
--pid-file=liyangyang.local.pid 
--socket=/tmp/mysql.sock
複製代碼
② 查看mysql配置文件加載狀況:
➜  ~ /usr/local/opt/mysql/bin/mysqld --verbose --help | grep -A 1 'Default options'
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf

# 概述:
① 服務器首先讀取的是 /etc/my.cnf文件

② 若是前一個文件不存在則繼續讀/etc/mysql/my.cnf文件,依此類推往下尋找,一直到最後一個~/.my.cnf文件

③ 若是以上全部文件都不存在;則說明安裝mysql以後未進行配置文件;能夠本身編輯一份名爲my.cnf;修改文件擁有者和所屬組且賦予可執行權限便可
       
       ① mkdir /usr/local/mysql/etc  

       ② vim /usr/local/mysql/etc/my.cnf  -- 內容能夠複製一份本地的配置文件便可

       ③ chown -R root:root /usr/local/mysql/etc/

       ④ chmod 755 /usr/local/mysql/etc/my.cnf
複製代碼
③ 查看mysql讀取配置文件方法:
## 查看是否使用了指定目錄的my.cnf
➜  ~ ps aux | grep mysql | grep 'my.cnf'

## 查看mysql默認讀取my.cnf的目錄
➜  ~ mysql --help | grep 'my.cnf'
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf

這些就是mysql默認會搜尋my.cnf的目錄,順序排前的優先;等同於上面搜索語句
複製代碼
④ 免密碼登陸並修改密碼
### mysql 5.8版本以前的修改方法:

① 在mysql配置文件中,[mysqld]下添加一行,使其登陸時跳過權限檢查
[mysqld]
skip_grant_tables

② 重啓mysql服務;登陸mysql -uroot -p

### mysql5.8版本以後修改方法:

    ① 執行目錄下執行,例如我本地運行地址:
    /usr/local/opt/mysql/bin/mysqld  -console --skip-grant-tables --shared-memory
    
    ② 新開啓一個窗口:mysqld -uroot -p 直接回車(你們能夠升級版本測試下)

### 以上操做完畢後 進度mysql終端,修改密碼:

set password for root@localhost = '新密碼';
或者
update user set authentication_string='新密碼' where user='root'; 
或者
alter user 'root'@'localhost' identified with mysql_native_password by '新密碼';

### 注意:刷新mysql相關權限
flush privileges;

### 最終流程:
mysql> update user set authentication_string='root' where user='root';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> set password for root@localhost = 'root';
Query OK, 0 rows affected (0.02 sec)

mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'root';
Query OK, 0 rows affected (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)

mysql> exit
Bye

此時再登陸時咱們的密碼已經更新爲root

複製代碼

三、沒法鏈接mysql服務器

報錯代碼:
~ mysql -uroot -p
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) 複製代碼
報錯緣由:
① mysql服務器沒有開啓

② mysql服務器開啓了,但不能找到 socket 文件

複製代碼
概述mysql的鏈接方式:
mysql的登錄方式有兩種,分別是socket和tcp/ip方式登錄

### socket(套接字)鏈接方式:

只能在mysql客戶端和數據庫實例在同一臺服務器上的狀況下使用(本地鏈接);

一般鏈接localhost是經過一個Unix域套接字文件進行,通常是/tmp/mysql.sock;

若套接字文件被刪除了,本地客戶就不能再鏈接了

### 登陸實例後查詢
mysql> show variables like 'socket';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| socket        | /tmp/mysql.sock |
+---------------+-----------------+
1 row in set (0.04 sec)

### 固然咱們也能夠經過socket文件登陸數據庫
➜  ~ mysql -uroot -proot -S /tmp/mysql.sock -- 用戶名 + 密碼 + Socket文件路徑地址(可不帶默認)
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
............. 省略部分
#### 注意事項:
mysql.sock必須是mysql中配置的文件且必須在/tmp下存在;若不存在則啓動不了mysql

### TCP/IP鏈接方式:
➜  ~ mysql -uroot -proot -h 127.0.0.1 -- 用戶名 + 密碼 + ip:port
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
............. 省略部分

#### 說明概述
若經過tcp/ip地址鏈接mysql;它將先檢查權限視圖表,檢測請求方的ip是否容許被鏈接
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select host, user from user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+
4 rows in set (0.00 sec)
    ① host 表示該用戶只能經過localhost的ip訪問此數據庫
    ② host:% 表示任何ip均可以鏈接mysql實例
複製代碼
問題解決方案:
① 修改配置文件增長socket路徑
       ➜  ~ vim /usr/local/etc/my.cnf
       [mysqld] 
       socket=/tmp/mysql.sock
② 使用軟鏈接將已經存在的mysql.sock軟鏈到/tmp/mysql.sock
       ln -s /usr/local/xxx/mysql.sock  /tmp/mysql.sock

③ 最最最暴力解決方案;卸載mysql,mysql相關的所有刪除;爲了實踐演示我本機mac刪除卸載重裝😭 😭 😭
       ➜  ~ brew remove mysql
       ➜  ~ brew cleanup
       ➜  ~ launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
       ➜  ~ rm ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
       ➜  ~ sudo rm -rf /usr/local/var/mysql
       ➜  ~ brew install mysql
       ➜  ~ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist --設置開機啓動
        /Users//Library/LaunchAgents/homebrew.mxcl.mysql.plist: service already loaded
複製代碼

四、沒法鏈接mysql服務器

報錯代碼:
~ mysql -uroot -p
ERROR!The server quit without updating PID file (/usr/local/var/mysql/***MacBook-Pro.local.pid) 複製代碼
報錯緣由:
① mysql服務器沒有開啓

② mysql服務器開啓了,但不能找到 socket 文件

複製代碼
問題解決方案:
sudo chown -R mysql:mysql /usr/local/mysql/
複製代碼

五、鏈接數過多,致使鏈接不上數據庫

報錯代碼:
~ mysql -uroot -p
ERROR 1040 (0000):Too many connections
複製代碼
報錯緣由:
① mysql連接數太多,已經超出咱們設置的默認連接數;致使連接不上數據庫,業務天然也拉跨了

② 可能存在mysql設置wait_timeout的值偏大,致使鏈接的空閒等待太長,則形成當前鏈接數變大
複製代碼
解決問題的思路:
### 查詢mysql數據庫當前設置的最大鏈接數

mysql> show variables like "%connections";
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| max_connections        | 151   |  -- mysql支持的最大鏈接
| max_user_connections   | 0     |  -- 用戶能最大鏈接進來的數量
| mysqlx_max_connections | 100   |  -- 能夠接受的最大併發客戶端鏈接數 跟max_connections相同;8.0版本增長
+------------------------+-------+
3 rows in set (0.01 sec)

### 再看看最大鏈接數
mysql> show status like 'Threads%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_cached    | 1     | -- 是指mysql管理的線程池中還有多少能夠被複用的資源
| Threads_connected | 5     | -- 是指打開的鏈接數;跟show processlist結果相同
| Threads_created   | 10    | -- 是指新建立的thread
| Threads_running   | 2     | -- 是指真正運行中的鏈接數;當前併發數量
+-------------------+-------+
4 rows in set (0.04 sec)

### 查看連接超時配置

mysql> show variables like '%timeout%';
+-----------------------------------+----------+
| Variable_name                     | Value    |
+-----------------------------------+----------+
| connect_timeout                   | 10       |
| delayed_insert_timeout            | 300      |
| have_statement_timeout            | YES      |
| innodb_flush_log_at_timeout       | 1        |
| innodb_lock_wait_timeout          | 50       |
| innodb_rollback_on_timeout        | OFF      |
| interactive_timeout               | 28800    | -- 服務器關閉交互式鏈接前等待活動的秒數
| lock_wait_timeout                 | 31536000 |
| mysqlx_connect_timeout            | 30       |
| mysqlx_idle_worker_thread_timeout | 60       |
| mysqlx_interactive_timeout        | 28800    | -- 服務器關閉交互式鏈接前等待活動的秒數
| mysqlx_port_open_timeout          | 0        |
| mysqlx_read_timeout               | 30       |
| mysqlx_wait_timeout               | 28800    | -- 等待交互式客戶端超時的秒數
| mysqlx_write_timeout              | 60       |
| net_read_timeout                  | 30       |
| net_write_timeout                 | 60       |
| rpl_stop_slave_timeout            | 31536000 |
| slave_net_timeout                 | 60       |
| wait_timeout                      | 28800    |  -- 服務器關閉非交互鏈接以前等待活動的秒數
+-----------------------------------+----------+
20 rows in set (0.00 sec)

複製代碼
問題解決方案:
### 設置最大鏈接數(必需要根據服務器的實際負載狀況來設置,不是很推薦)
① mysql> set global max_connections =200;
  Query OK, 0 rows affected (0.00 sec)

② mysql> set global max_user_connections =100;
  Query OK, 0 rows affected (0.00 sec)
   
③ mysql> set global mysqlx_max_connections =100;
  Query OK, 0 rows affected (0.00 sec)

### 重啓mysql服務,釋放部分連接
systemctl start mysqld.service

### 若是是由於等待超時時間太長引發能夠修改時間 (不推薦)
① mysql> set interactive_timeout =31536000;
  Query OK, 0 rows affected (0.00 sec)

② mysql> set wait_timeout =31536000;
  Query OK, 0 rows affected (0.00 sec)
  
以上均可以經過修改mysql的配置文件重啓生效
複製代碼

調整最大鏈接數:存在安全隱患,咱們沒法確認數據庫能承受最大鏈接壓力;就比如你一天能作3個需求,忽然組長給你10需求,讓你何時提測;那確定接受不了啊,隨時陷入奔潰邊緣,脾氣瞬間暴漲,離職了不幹了。redis

涉及業務:① 寫業務操做數據庫結束以後必定要釋放當前的連接;② 系統初始化建立一塊鏈接池;用戶訪問數據庫時,從鏈接池中取出一個已創建的空閒鏈接對象;使用完畢以後,並非關閉鏈接,而是放回鏈接池給下一個請求使用sql

六、mysql5.7版本only_full_group_by致使原sql語句報錯

報錯代碼:
1055 - Expression #4 of SELECT list is not in GROUP BY clause and contains 
nonaggregated column 'table.starttime' which is not functionally dependent on columns 
in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
複製代碼
報錯緣由:

mysql5.7版本以後only_full_group_by字段就爲真;字面意思就是select後面查詢的字段沒有出如今group by 中,致使報錯。數據庫

核心原則:① select、having或order by後面存在的非聚合列必須所有在group by中存在; ② order by後面的列必須是在select後面存在的vim

問題解決方案:
### 第一種方案:
去掉only_full_group_by規則配置

### 第二種方案:
修改業務sql語句使其遵照only_full_group_by規則

### 第三種
mysql版本降到5.7如下版本
複製代碼

第一種方案:推薦使用;緣由相對來講風險較小簡單操做,以下:centos

## 查看下SQL的模式
mysql> show variables like '%sql_mode%';  -- 第一個指令
mysql> SELECT @@sql_mode;  -- 第二個指令
mysql> SELECT @@GLOBAL.sql_mode; --第三個指令
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                 |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

說明本地的mysql是開啓了規則校驗

### 關閉only_full_group_by的規則校
    ① set sql_mode = '' 
    或者 
    set sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
    或者
    set @@GLOBAL.sql_mode= 'xxx'  set @@SESSION.sql_mode= 'xxx'
    #### 注意事項
        此設置只針對你當前修改生效,一旦mysql重啓之後則會被當即還原的;須要到mysql的配置文件中增長次選項,而後重啓生效。
複製代碼

第二種方案:若是是新項目推薦使用,則改動較小;如是就項目升mysql版本,基本上項目sql沒有遵循only_full_group_by規則,修改爲本較高,且須要測試介入全面測試,人力成本在這裏;且存在潛在測不到的問題安全

第三種方案:不建議使用;降級版本不知道會出現其餘的問題,風險較大,安全度不夠高服務器

七、編碼錯誤

報錯代碼:
SQL Error: 1366: Incorrect string value: "xBB\x86…" for column "user_name" at row 1 
複製代碼
報錯緣由:

由於insert into插入的數據時,某一個字段帶有表情(微信登陸);正常utf-8編碼可能有2,3,4字節,那麼emoji表情或者某些特殊字符是4個字節,而mysql的utf8編碼最多3個字節,因此致使插入數據失敗;應該不少初學者會遇到這樣的問題微信

問題解決方案:
### 查看mysql配置的字符集
mysql> show variables like 'character_set_%';
+--------------------------+------------------------------------------------------+
| Variable_name            | Value                                                |
+--------------------------+------------------------------------------------------+
| character_set_client     | utf8mb4                                              |
| character_set_connection | utf8mb4                                              |
| character_set_database   | utf8mb4                                              |
| character_set_filesystem | binary                                               |
| character_set_results    | utf8mb4                                              |
| character_set_server     | utf8mb4                                              |
| character_set_system     | utf8                                                 |
| character_sets_dir       | /usr/local/Cellar/mysql/8.0.19/share/mysql/charsets/ |
+--------------------------+------------------------------------------------------+
8 rows in set (0.00 sec)
## 參數說明:
① character_set_client      -- 用來設置客戶端使用的字符集
② character_set_connection  -- 用來設置鏈接數據庫時的字符集,若是程序中沒有指明鏈接數據庫使用的字符集類型則按照這個字符集設置
③ character_set_database    -- 用來設置默認建立數據庫的編碼格式,若是在建立數據庫時沒有設置編碼格式,就按照這個格式設置
④ character_set_filesystem  -- 文件系統的編碼格式,把操做系統上的文件名轉化成此字符集,即把 character_set_client轉換character_set_filesystem, 默認binary是不作任何轉換的
⑤ character_set_results     -- 數據庫給客戶端返回時使用的編碼格式,若是沒有指明,使用服務器默認的編碼格式
⑥ character_set_server      -- 服務器安裝時指定的默認編碼格式,這個變量建議由系統本身管理,不要人爲定義
⑦ character_set_system     -- 數據庫系統使用的編碼格式,這個值一直是utf8,不須要設置,它是爲存儲系統元數據的編碼格式
⑧ character_sets_dir       -- 字符集安裝的目錄

### 修改配置文件
[mysql]
default-character-set=utf8mb4
[mysqld]
character_set_server=utf8mb4 #設置字符集

### 修改數據庫字符集
ALTER database 數據庫名 CHARACTER SET utf8mb4;
修改完數據庫字符集,須要重啓mysql數據庫;且只對新表有做用
### 修改表的字符集
ALTER TABLE  表名 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
只對該表的新行有用,以前的表無做用
複製代碼

八、mysql數據庫導入sql文件報1153

報錯代碼:
Error Code: 1153 - Got a packet bigger than 'max_allowed_packet' bytes
複製代碼
報錯緣由:

小夥伴們可能常常性使用navicat客戶端軟件或者其餘mysql客戶端軟件導入sql數據,文件小點可能沒有太大問題,可是一旦文件幾十兆或者幾百兆就會報上面的錯誤:具體是受限於mysql默認讀取sql的文件大小markdown

問題解決方案:
### 先查看下默認讀取sql文件大小
mysql> show VARIABLES like '%max_allowed_packet%';
+---------------------------+------------+
| Variable_name             | Value      |
+---------------------------+------------+
| max_allowed_packet        | 67108864   | -- 指mysql服務器端和客戶端在一次傳送數據包的過程中最大容許的數據包大小 64M
| mysqlx_max_allowed_packet | 67108864   | 
| slave_max_allowed_packet  | 1073741824 |
+---------------------------+------------+
3 rows in set (0.00 sec)

### ① 臨時修改默認大小
mysql> set global max_allowed_packet = 16*1024*1024;
Query OK, 0 rows affected (0.01 sec)
--- 修改完以後須要退出從新進入mysql
mysql> show VARIABLES like '%max_allowed_packet%';
+---------------------------+------------+
| Variable_name             | Value      |
+---------------------------+------------+
| max_allowed_packet        | 16777216   | -- 16M
+---------------------------+------------+
3 rows in set (0.00 sec)

### ② 修改配置文件my.cnf(找不到配置文件:mysql --help | grep my.cnf)
[mysqld]
max_allowed_packet = 20M
複製代碼

九、建立mysql數據庫或者表顯示1044無權限建立

報錯代碼:
mysql> use test;
ERROR 1044 (42000): Access denied for user 'root1'@'localhost' to database 'test'
複製代碼
報錯緣由:

當前root1帳號沒有授予建立數據庫或者數據表的權限。

問題解決方案:
### 查看帳號權限
mysql> show grants for root1@localhost;
+-------------------------------------------+
| Grants for root1@localhost                |
+-------------------------------------------+
| GRANT USAGE ON *.* TO `root1`@`localhost` |
+-------------------------------------------+
1 row in set (0.01 sec)
### 直觀查看root1權限
mysql> select * from mysql.user where user='root1' and host='localhost' \G;
*************************** 1. row ***************************
                    Host: localhost
                    User: root1
             Select_priv: N
             Insert_priv: N
             Update_priv: N
             Delete_priv: N
             Create_priv: N
               Drop_priv: N
             Reload_priv: N
           Shutdown_priv: N
         ....................
1 row in set (0.00 sec)

### 賦予root1帳號全部權限
mysql> grant all privileges on *.* to 'root1'@'localhost' with grant option;
Query OK, 0 rows affected (0.02 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
mysql> show grants for root1@localhost;
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root1@localhost                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `root1`@`localhost` WITH GRANT OPTION                                                                                                           |
| GRANT APPLICATION_PASSWORD_ADMIN,AUDIT_ADMIN,BACKUP_ADMIN,BINLOG_ADMIN,BINLOG_ENCRYPTION_ADMIN,CLONE_ADMIN,CONNECTION_ADMIN,ENCRYPTION_KEY_ADMIN,GROUP_REPLICATION_ADMIN,INNODB_REDO_LOG_ARCHIVE,PERSIST_RO_VARIABLES_ADMIN,REPLICATION_APPLIER,REPLICATION_SLAVE_ADMIN,RESOURCE_GROUP_ADMIN,RESOURCE_GROUP_USER,ROLE_ADMIN,SERVICE_CONNECTION_ADMIN,SESSION_VARIABLES_ADMIN,SET_USER_ID,SYSTEM_USER,SYSTEM_VARIABLES_ADMIN,TABLE_ENCRYPTION_ADMIN,XA_RECOVER_ADMIN ON *.* TO `root1`@`localhost` WITH GRANT OPTION |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
此時再去建立數據庫或表操做都是ok的了
複製代碼

十、撤銷用戶權限報錯

報錯代碼:
ERROR 1227 (42000): Access denied; you need (at least one of) the SYSTEM_USER privilege(s) for this operation
複製代碼
報錯緣由:

因本地mysql的版本是8.0以上,因此在root下建立新用戶時會給新用戶賦予SYSTEM_USER權限,可是本身自己是沒有該權限的,因此致使root帳號下對新用戶進行撤銷帳號權限報錯。

問題解決方案:
### 第一種方案:新用戶root1下操做
mysql> grant system_user on *.* to root;
Query OK, 0 rows affected (0.04 sec)
// 切換到root用戶下對root1用戶取消權限
mysql> revoke all privileges on *.* from oot1; 
Query OK, 0 rows affected (0.01 sec)

### 第二種方案:新用戶帳號下直接取消本身所有權限
mysql> revoke all privileges on *.* from root1;
Query OK, 0 rows affected (0.01 sec)
複製代碼

十一、插入重複數據因惟一建失敗

報錯代碼:
ERROR 1062 (23000): Duplicate entry 'amu-1' for key 'test.uniq_flag'
複製代碼
報錯緣由:

因數據表設置了惟一鍵,致使插入重複數據失敗;流程以下:

mysql> CREATE TABLE `test` (
    ->   `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
    ->   `uniq_flag` varchar(64) NOT NULL DEFAULT ''COMMENT '惟一建',
    ->   PRIMARY KEY (`id`),
    ->   UNIQUE KEY `uniq_flag` (`uniq_flag`) USING BTREE
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='測試表';
    Query OK, 0 rows affected, 1 warning (0.04 sec)
    
mysql> insert into test(`uniq_flag`) values('amu-1');
Query OK, 1 row affected (0.02 sec)

mysql> select * from test;
+----+-----------+
| id | uniq_flag |
+----+-----------+
|  1 | amu-1     |
+----+-----------+
1 row in set (0.00 sec)

mysql> insert into test(`uniq_flag`) values('amu-1');
ERROR 1062 (23000): Duplicate entry 'amu-1' for key 'test.uniq_flag'
複製代碼
問題解決方案:
①  方案一:作好業務程序上的判斷,若返回狀態碼是1062則能夠記錄日誌,不報致命錯誤(推薦使用)

② 方案二:忽略致命報錯 insert ignore  into
        mysql> insert ignore  into  test(`uniq_flag`) values('amu-1');
        Query OK, 0 rows affected, 1 warning (0.01 sec)
    注意:出現錯誤時,只會以警告形式返回;要保證自身的sql語句ok,不然ignore會忽略掉全部報錯 (不建議使用)
    
③ 方案三:插入數據時先查詢後插入 insert … select … where not exist  
        insert into test(`uniq_flag`) 
        SELECT 'amu-1' FROM dual WHERE NOT EXISTS 
        (SELECT uniq_flag FROM test WHERE uniq_flag = 'amu-1');
        經過select來檢測判斷是否插入;存在則不插入不然插入數據。 (不推薦使用)

④ 方案四:檢測存在相同數據先刪除,再從新插入 replace into
        mysql> replace into test(`uniq_flag`) values('amu-2');
        Query OK, 2 rows affected (0.00 sec)
    注意:對業務需求沒有影響可使用,假如存在對數據的統計等等有負面影響則推薦使用第一種方案,程序作兼容判斷處理 (能夠推薦使用)
複製代碼

十二、未知的字段名 name(小夥伴提交代碼review發現的)

報錯代碼:
mysql> select ids  from test;
ERROR 1054 (42S22): Unknown column 'name' in 'field list'
複製代碼
報錯緣由:

寫sql語句時出現了指定表中沒有的字段名稱,就會出現這個錯誤。

  • ① 可能開發對錶字段在測試環境進行增長或者修改,未同步到線上;致使代碼上線出現這種狀況
  • ② 若存在多主多從集羣,存在修改表結構未及時同步到從庫;致使程序讀從庫報錯
  • ③ 極大多是開發編碼不夠細心,這種低級錯誤不能犯;全部的sql語句都要通過expline和測試環境的驗證;未作到代碼review工做

總結

以上只是總結了部分mysql的常見報錯問題的案例分析解決方案;也會繼續總結mysql的錯誤案例分享出來。不足之處,但願小夥伴們指正。

好了,我是阿沐,一個不想30歲就被淘汰的打工人 ⛽️ ⛽️ ⛽️ 。創做不易以爲「阿沐」寫的有點料話:👍 關注一下,💖 分享一下,咱們下期再見。

相關文章
相關標籤/搜索