DB version: 8.0.25 - 阿里RDS
監(jiān)控收到一條告警信息,于是連上DB查看Processlist

processlist.png
發(fā)現(xiàn)一條慢查詢,USER字段為root賬號,HOST字段是%,覺得很詭異:
1.root賬號密碼只有本人持有,應用連接是另外一個單獨賬號
2.HOST字段來源IP是%,正常情況下應該是IP地址才對
3.此SQL執(zhí)行為何這么久?
針對以上第3個問題,排查到為SQL中調(diào)用了一個函數(shù),如果函數(shù)的入?yún)镹ULL則會導致執(zhí)行死循環(huán),也正是調(diào)用了函數(shù),才會出現(xiàn)USER=‘yd_root’和HOST=‘%’的情況。
后面在阿里云 RDS 文檔找到一篇關(guān)于%的說明,在最下面常見問題,鏈接:https://help.aliyun.com/document_detail/94842.html?spm=5176.2020520104.0.0.1155709akPIYwv 文章中提到調(diào)用存儲過程可能會出現(xiàn),經(jīng)測試,發(fā)現(xiàn)調(diào)用存過,函數(shù),Event的時候都會出現(xiàn)類似情況,其他場景暫沒想到。
測試前先創(chuàng)建一個臨時賬號:
create user test_user@'%' identified by "test_user";
grant all on *.* to test_user@'%' ;
1.測試調(diào)用存過
-- session1: 登錄root賬號
# 創(chuàng)建存儲過程,其中 DEFINER=`root`@`%`
USE test;
DELIMITER $$
DROP PROCEDURE IF EXISTS `das` $$
CREATE DEFINER=`root`@`%` PROCEDURE `das`()
BEGIN
SELECT * FROM information_schema.processlist WHERE Id = CONNECTION_ID();
END $$
DELIMITER;
# session2: 登錄test_user賬號執(zhí)行存儲過程,得到預期結(jié)果的USER和HOST
USE test;
CALL das();
ID USER HOST DB COMMAND TIME STATE INFO
178616 root %:52958 test Query 0 executing SELECT * FROM information_schema.processlist WHERE Id = CONNECTION_ID()
# session3: 用root賬號執(zhí)行存過會得到正確的HOST
結(jié)果略
2.測試調(diào)用函數(shù)
-- session1: 登錄root賬號
# 創(chuàng)建函數(shù),其中 DEFINER=`root`@`%`
USE test;
DELIMITER $$
DROP FUNCTION IF EXISTS `das` $$
CREATE DEFINER=`root`@`%` FUNCTION `das`(cid int) RETURNS VARCHAR(100)
BEGIN
declare v_user VARCHAR(50) ;
declare v_host VARCHAR(50) ;
SELECT user,host into v_user,v_host FROM information_schema.processlist WHERE Id = cid;
return concat('USER:',v_user,' ','HOST:',v_host);
END $$
DELIMITER;
# session2: 登錄test_user賬號執(zhí)行函數(shù),得到預期結(jié)果的USER和HOST
USE test;
select das(CONNECTION_ID()) as res ;
res
USER:root HOST:%:52958
# session3: 用root賬號執(zhí)行函數(shù)會得到正確的HOST
結(jié)果略
3.測試調(diào)用event
event不涉及 存過 或者 函數(shù) 的時候是不會出現(xiàn)HOST字段%的情況的
#模擬下event調(diào)用存過出現(xiàn)`%`的場景:
# 登錄root賬號,創(chuàng)建表及存儲過程
use test ;
create table t_event(id int auto_increment PRIMARY key , name VARCHAR(10)) ;
# 創(chuàng)建存儲過程,其中 DEFINER=`root`@`%`
use test;
DELIMITER $$
DROP PROCEDURE IF EXISTS `das` $$
CREATE DEFINER=`root`@`%` PROCEDURE `das`()
BEGIN
insert into t_event (name) select concat(sleep(2),'ccc');
END $$
DELIMITER;
# 創(chuàng)建event
use test;
CREATE DEFINER=`root`@`%` EVENT IF NOT EXISTS `test`.`t_event`
ON SCHEDULE
EVERY '2' SECOND
DO call test.das();
# 查看processlist
SELECT *from information_schema.`PROCESSLIST` where id <>CONNECTION_ID() and info <> '' ;
ID USER HOST DB COMMAND TIME STATE INFO
1487 root % test Connect 1 User sleep insert into t_event (name) select concat(sleep(2),'ccc')
模擬下event調(diào)用函數(shù)出現(xiàn)%的場景:
略