MySQL存儲(chǔ)過程未執(zhí)行的問題排查過程
1. 問題背景
最近部署了一套測(cè)試環(huán)境,同事發(fā)現(xiàn)以前遺留的一個(gè)存儲(chǔ)過程未運(yùn)行,需要我?guī)兔ε挪橄?。下面說一下我的排查過程。列出每種可能得原因以及考慮。
2. 問題排查
2.1. 數(shù)據(jù)庫版本升級(jí)的問題
之前我們用的是 8.0.x 版本的 MySQL,最近運(yùn)維將數(shù)據(jù)庫升級(jí)到了 8.4.3 版本。剛開始懷疑是數(shù)據(jù)庫升級(jí)導(dǎo)致的,查了相關(guān)的版本說明,并沒有發(fā)現(xiàn)會(huì)導(dǎo)致存儲(chǔ)過程不執(zhí)行的問題。
2.2. 用戶權(quán)限不足的問題
檢查了存儲(chǔ)過程中定義的用戶為root
@%
,并查看了權(quán)限,發(fā)現(xiàn)沒有問題。
這里記錄下涉及到的查詢:
用戶權(quán)限查詢
確保執(zhí)行存儲(chǔ)過程的用戶有足夠的權(quán)限。你可以使用如下命令查看權(quán)限:
SHOW GRANTS FOR 'your_username'@'your_host';
并確保有 EXECUTE 和 ALTER ROUTINE 權(quán)限。如果沒有,你可以通過以下命令授予權(quán)限:
GRANT EXECUTE, ALTER ROUTINE ON your_database_name.* TO 'your_username'@'your_host';
查詢命令解析
SHOW GRANTS FOR `root`@`%`;
這條 SQL 命令在 MySQL 數(shù)據(jù)庫中用來展示用戶名為 root,且可以從任意主機(jī)(由%
表示)連接到 MySQL 服務(wù)器的用戶的權(quán)限。
- root 用戶:root 是 MySQL 的默認(rèn)超級(jí)用戶,擁有對(duì)數(shù)據(jù)庫的完全訪問權(quán)限,包括創(chuàng)建、修改、刪除數(shù)據(jù)庫和數(shù)據(jù)表,以及管理用戶權(quán)限等。
- % 的含義:
%
在 MySQL 中表示任意主機(jī),即 root 用戶可以從任何主機(jī)連接到 MySQL 服務(wù)器。
如果在執(zhí)行 SHOW GRANTS FOR 'root'@'%';
后發(fā)現(xiàn)結(jié)果中缺少 EXECUTE
權(quán)限,表示 root
用戶當(dāng)前沒有被授予執(zhí)行存儲(chǔ)過程或函數(shù)的權(quán)限。EXECUTE
權(quán)限是 MySQL 中用于執(zhí)行存儲(chǔ)過程和存儲(chǔ)函數(shù)的權(quán)限。
可以使用 GRANT
語句為 root
用戶添加 EXECUTE
權(quán)限:
GRANT EXECUTE ON *.* TO 'root'@'%'; FLUSH PRIVILEGES;
這條命令做了以下幾件事:
GRANT EXECUTE ON *.* TO 'root'@'%';
:為root
用戶授予在所有數(shù)據(jù)庫和所有表上的EXECUTE
權(quán)限。*.*
表示所有數(shù)據(jù)庫和所有表,你也可以根據(jù)需要指定特定的數(shù)據(jù)庫或表。FLUSH PRIVILEGES;
:刷新 MySQL 的權(quán)限緩存,使新的權(quán)限設(shè)置立即生效。
2.3. 存儲(chǔ)過程本身的問題
首先這個(gè)存儲(chǔ)過程在生產(chǎn)環(huán)境還有其他環(huán)境都是可以正常運(yùn)行的。因?yàn)槭菑?fù)制過來的,所以一開始我就沒想到這個(gè)錯(cuò)誤。但是排查到這里后,還是使用CALL()
去手動(dòng)調(diào)度了一下該存儲(chǔ)過程,竟然執(zhí)行報(bào)錯(cuò)了,報(bào)錯(cuò)如下:
1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'Newton.imsi_transaction_cdr_raw_cn.carrier_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
這下感覺終于有眉目了,這明顯是 SQL 模式導(dǎo)致的問題。查看了下存儲(chǔ)過程的語句,里面還真有GROUP BY
,并且不符合ONLY_FULL_GROUP_BY
模式的要求。存儲(chǔ)過程未執(zhí)行的原因找到了,我想著接下來去除掉該 SQL 模式應(yīng)該就能解決問題了。
我趕緊去查了一下當(dāng)前的全局 SQL 模式和當(dāng)前會(huì)話 SQL 模式,傻眼了,SQL 模式中并沒有ONLY_FULL_GROUP_BY
模式,這時(shí)我想起來了,當(dāng)時(shí)環(huán)境部署完后,我就要求運(yùn)維將該ONLY_FULL_GROUP_BY
模式去掉了,那為啥現(xiàn)在還會(huì)報(bào)這種錯(cuò)誤,不應(yīng)該啊,想不明白。
這里記錄下 MySQL 查詢 SQL 模式并去除 ONLY_FULL_GROUP_BY 的語句:
查詢?nèi)?SQL 模式,全局SQL模式影響所有新的會(huì)話(連接),但不影響已經(jīng)存在的會(huì)話
SELECT @@GLOBAL.sql_mode;
查詢當(dāng)前會(huì)話SQL模式,當(dāng)前會(huì)話 SQL 模式僅影響當(dāng)前連接
SELECT @@SESSION.sql_mode;
或者,更簡潔地:
SELECT @@sql_mode;
臨時(shí)去除 ONLY_FULL_GROUP_BY(僅影響當(dāng)前會(huì)話)
使用SET SESSION
語句來更改當(dāng)前會(huì)話的 SQL 模式:
SET SESSION sql_mode = REPLACE(@@SESSION.sql_mode, 'ONLY_FULL_GROUP_BY', '');
永久去除 ONLY_FULL_GROUP_BY(影響所有新會(huì)話)
要永久更改全局 SQL 模式,需要編輯 MySQL 的配置文件(如my.cnf
或my.ini
),然后重啟 MySQL 服務(wù)。但是,直接修改全局 SQL 模式可能會(huì)影響其他用戶和應(yīng)用,因此通常建議只在必要時(shí)進(jìn)行此類更改。
操作步驟:
- 打開MySQL配置文件。
- 找到
[mysqld]
部分。 - 修改或添加
sql_mode
行,確保不包含ONLY_FULL_GROUP_BY
。 - 保存文件并重啟 MySQL 服務(wù)。
例如,配置文件中的設(shè)置可能如下所示:
[mysqld] sql_mode = "STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,...(其他模式,但不包括ONLY_FULL_GROUP_BY)"
3. 問題解決
目前情況是 MySQL 8.4.3 版本,我明明之前已經(jīng)去掉了 ONLY_FULL_GROUP_BY 模式,為什么調(diào)用存儲(chǔ)的時(shí)候還會(huì)報(bào) 1055 的錯(cuò)誤?
錯(cuò)誤提示很明顯,肯定是 ONLY_FULL_GROUP_BY 模式導(dǎo)致的,現(xiàn)在就是要找到為什么明明沒有該模式,怎么還會(huì)報(bào)這個(gè)錯(cuò)誤。
在網(wǎng)上查資料的過程中,就在百思不解的時(shí)候,不經(jīng)意看到了一處說明:
存儲(chǔ)過程內(nèi)部的 sql_mode:存儲(chǔ)過程在創(chuàng)建時(shí)可能會(huì)捕獲當(dāng)前的 sql_mode 設(shè)置,并在每次執(zhí)行時(shí)使用該設(shè)置。如果存儲(chǔ)過程是在 ONLY_FULL_GROUP_BY 模式啟用時(shí)創(chuàng)建的,那么即使你在之后禁用了該模式,存儲(chǔ)過程內(nèi)部仍然可能使用舊的 sql_mode。要解決這個(gè)問題,需要重新創(chuàng)建存儲(chǔ)過程,確保在創(chuàng)建時(shí) ONLY_FULL_GROUP_BY 模式是禁用的。
好吧,問題明朗了,當(dāng)時(shí)是這樣的,運(yùn)維那邊創(chuàng)建好數(shù)據(jù)庫后,我進(jìn)行庫表和存儲(chǔ)過程的初始化,服務(wù)部署后,通過服務(wù)日志發(fā)現(xiàn)有GROUP BY
報(bào)錯(cuò),才找的運(yùn)維去掉了 ONLY_FULL_GROUP_BY 模式,也就是說存儲(chǔ)過程創(chuàng)建的時(shí)候,數(shù)據(jù)庫的 SQL 模式中是含有 ONLY_FULL_GROUP_BY 模式的。所以存儲(chǔ)過程內(nèi)部的 sql_mode 肯定也是含有 ONLY_FULL_GROUP_BY 模式的,所以會(huì)報(bào) 1055 錯(cuò)誤。
那解決辦法就很簡單了,刪除掉當(dāng)前的存儲(chǔ)過程,重新創(chuàng)建即可,我試了下,重新創(chuàng)建后,手動(dòng)調(diào)用了下,果然正常執(zhí)行了。至此,問題解決!
以上就是MySQL存儲(chǔ)過程未執(zhí)行的問題排查過程的詳細(xì)內(nèi)容,更多關(guān)于MySQL存儲(chǔ)過程未執(zhí)行的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mysql四種分區(qū)方式以及組合分區(qū)落地實(shí)現(xiàn)詳解
對(duì)用戶來說,分區(qū)表是一個(gè)獨(dú)立的邏輯表,但是底層由多個(gè)物理子表組成,下面這篇文章主要給大家介紹了關(guān)于Mysql四種分區(qū)方式以及組合分區(qū)落地實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-04-04與MSSQL對(duì)比學(xué)習(xí)MYSQL的心得(七)--查詢
在這個(gè)《與MSSQL對(duì)比學(xué)習(xí)MYSQL的心得》系列里面,我一直都把MYSQL跟SQLSERVER進(jìn)行比較,相互進(jìn)行比較是學(xué)習(xí)一樣?xùn)|西比較好的方法2014-08-08MySQL數(shù)據(jù)庫表修復(fù) MyISAM
這篇文章主要介紹了MySQL數(shù)據(jù)庫表修復(fù) MyISAM ,需要的朋友可以參考下2014-06-06MySQL去除重疊時(shí)間求時(shí)間差和的實(shí)現(xiàn)
在生產(chǎn)中常常出現(xiàn)計(jì)算兩個(gè)時(shí)間差的業(yè)務(wù),比如總宕機(jī)時(shí)間、總開通會(huì)員時(shí)間等,本文就詳細(xì)的來介紹一下如何計(jì)算,感興趣的可以了解一下2021-08-08MySQL中rank() over、dense_rank() over、row_number()&n
本文主要介紹了MySQL中rank() over、dense_rank() over、row_number() over用法介紹,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03