进程列表将“%”显示为来自触发器的主机

pmc*_*try 3 mysql trigger insert

我试图用调用者的主机/IP 填充表中的某个列。我在表上有一个插入触发器,它像这样设置列:

CREATE TRIGGER access_insert_trg BEFORE INSERT ON access
FOR EACH ROW 
set NEW.hostname = (select SUBSTRING_INDEX(host,':',1)
                    from information_schema.processlist 
                    WHERE ID=connection_id())
;
Run Code Online (Sandbox Code Playgroud)

%尽管当我在processlist表上手动运行相同的查询时,我得到了实际的主机名,但我最终还是得到了主机名。我已经检查了该connection_id()值,它是在主机列中processlist具有实际hostname:port值的行的 id 正确。

我无法弄清楚它是如何或为什么被转换为通用%:<port>值的。关于发生了什么以及如何解决它的任何想法?

如果有任何改变,我正在使用 MySQL 5.1.57。

Mic*_*bot 5

您是否正在执行从存储过程内部触发触发器的插入操作?

显然,当在存储过程中时,如果调用用户与定义者不同,则在 information_schema.processlist 中匹配您的线程的行将填充(尽管有点半心半意)DEFINER 用户名和主机名。

这有点出乎意料,所以我会在下面记录更多...

但首先,你的修复:

SET NEW.hostname = SUBSTRING_INDEX(user(),'@',-1);
Run Code Online (Sandbox Code Playgroud)

如果这行得通,那绝对是一种更好的方法——它是一种更轻量级的方式来获取您正在寻找的信息,并且似乎返回正确的答案,而另一个则没有。调用 information_schema.processlist 的开销很大,因为显然每次调用它时都会呈现整个表


现在,为了那些(包括我在内)在没有看到它的实际行动的情况下不会相信它的人(包括我在内)的利益而复制该行为:

DELIMITER $$

DROP PROCEDURE IF EXISTS `bizarre` $$
CREATE DEFINER=`super_dev`@`%` PROCEDURE `bizarre`()
BEGIN

SELECT * FROM information_schema.processlist WHERE Id = CONNECTION_ID();

END $$

DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

现在来测试SP。请注意,我不是以 super_dev 身份连接,而是以其他超级用户身份连接。如果我以 super_dev(DEFINER 用户)身份连接,这将按我们预期的方式工作。

mysql> call bizarre();
+-------+---------------+---------+------------+---------+------+-----------+-------------------------------------------------------------------------+
| ID    | USER          | HOST    | DB         | COMMAND | TIME | STATE     | INFO                                                                    |
+-------+---------------+---------+------------+---------+------+-----------+-------------------------------------------------------------------------+
| 17261 | super_dev     | %:49730 | dev_testsv | Query   |    0 | executing | SELECT * FROM information_schema.processlist WHERE Id = CONNECTION_ID() |
+-------+---------------+---------+------------+---------+------+-----------+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我最好的猜测是,这是调用存储过程时需要在内部发生的环境更改的工件。