MySQL触发器获取触发器触发的当前查询

3
我已经在网络上搜寻了4个小时,试图找到一个解决方案,但是我所能找到的只有以下内容:
你不能。 不可能。 不会发生。
我不喜欢那种方法。
我的理论是,如果它在information_schema.processlist中被存储了,那么就必须有一种方法来获取它。 我尝试让触发器在processlist表上运行,但无法让其工作,我认为这是因为它是一个视图。 运行日志不是一个选项,因为这会影响已经拥挤的服务器性能,而且有许多查询正在运行,我只想在特定表上记录更新。
这是传说中的stackoverflow! 在这里,您可以找到所有问题的解决方案,因为它充满了天才!
所以,我恳求,请出现吧! 真正的天才!:-)
谢谢, Zedd

我已经尝试过这个了,我成功地得到了在SQL Server 2000中运行的代码,但在MySQL中却不行。 - Romil Kumar Jain
该查询可以通过使用这个答案中提到的方法,由Itay Grudev获得。 - TiLogic
3个回答

2
问题在于MySQL触发器的作用域是行级别而不是语句级别。因此,在触发器内,您可以访问给定行中每个列的OLD和NEW值,但是您无法访问导致触发器触发的语句。
关于information_schema.processlist,实际上没有任何内容被“存储”(持久化)在该视图中。它只是一个SQL接口到进程列表,并且在触发器范围内无法访问导致触发器触发的语句。
您说您不想启用常规查询日志,并且这种方法不完美,原因有多种(包括事件时间的粒度为1秒),但以下是一个使用general_log表重新编写触发器的示例:
SET GLOBAL GENERAL_LOG='ON';
SET GLOBAL LOG_OUTPUT='TABLE';

DELIMITER || 

CREATE TRIGGER DEBUG_DATE BEFORE UPDATE ON db.tbl FOR EACH ROW 
BEGIN 
  DECLARE Q MEDIUMTEXT; 
  SELECT argument INTO Q 
  FROM mysql.general_log 
  where thread_id = connection_id() 
  order by event_time desc 
  limit 1;

  INSERT INTO db.tbl_log (INFO) 
  VALUES (Q); 

END ||

DELIMITER ;

1
我们调查了这个问题,并发现在上面的示例中 "DECLARE" 无法正常工作, 此外,服务器上应该启用 general_log 标志。最后,我们有以下触发器代码:
DELIMITER $$

DROP TRIGGER IF EXISTS `our_trigger`$$
CREATE TRIGGER `our_trigger` 
BEFORE UPDATE ON `our_table_for_debug` 
FOR EACH ROW BEGIN 

SELECT argument INTO @tquery FROM mysql.general_log where thread_id = connection_id() and argument like 'update%' order by event_time desc limit 1;
INSERT INTO `our_log_table` (`query`) VALUES (@tquery);

END IF;

END$$

DELIMITER ;

"

\"our_log_table\"是一张只有一个名为query的mediumtext字段的表。 要启用通用日志,您应该运行此查询:general_log = 1; 或直接在MySQL设置中启用它。

"

0
SELECT INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ... ;

1
那个不起作用。我已经尝试过了。这是我尝试过的触发器代码:DELIMITER || CREATE TRIGGER DEBUG_DATE BEFORE UPDATE ON db.tbl FOR EACH ROW BEGIN DECLARE Q VARCHAR(1024); SELECT INFO INTO Q FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID=CONNECTION_ID(); INSERT INTO db.tbl_log (INFO) VALUES (Q); END|| - Zedd
@user1403127:你得到了什么错误?你可能会得到多个结果(至少一个是触发器调用的UPDATE命令,另一个是触发器运行的SELECT INFO FROM INFORMATION_SCHEMA.PROCESSLIST命令),这些结果无法分配给你的Q变量。为什么不直接使用INSERT INTO db.tbl_log (INFO) SELECT INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID=CONNECTION_ID();呢?或者在你的WHERE子句中更加具体(考虑过滤COMMAND和/或STATE)? - eggyal
1
我也尝试过那个方法,但结果还是一样的。它只会将最后一个查询插入到 tbl_log 中,而这个查询通常是从进程列表中选择的。 - Zedd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接