在插入或更新时获取完整的MySQL查询字符串

时间:2012-05-17 00:56:10

标签: mysql logging triggers

需要MySQL的帮助,因为它不是我的强项。所以任何帮助都表示赞赏。

我的网站上存在UPDATEINSERT缺少值的问题。这导致了网站上其他功能的一些问题,但我无法找到UPDATEINSERT在任何类中完成的位置。

有没有办法,也许是MySQL触发器,我可以添加到这些表格中,这样我就可以存储UPDATEINSERT的原始或完整查询。我已经尝试过记录,但这适用于整个数据库,并且它占用了太多的磁盘空间。

提前感谢您的回复。

PS:目前,由于我们还处于开发阶段,PHP类有点乱,因此在更新或插入函数中添加例外将花费太多时间。所以请把重点放在问题的答案上。再次感谢。

8 个答案:

答案 0 :(得分:33)

您可以使用以下语句将当前SQL查询作为字符串获取:

SELECT info FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id = CONNECTION_ID()

所以你要做的就是创建一个TRIGGER,它运行在你的表上的插入和/或更新操作上,应该(i)获取当前的sql语句和(ii)将其插入另一个表中,如下所示:

DELIMITER |

CREATE TRIGGER log_queries_insert BEFORE INSERT ON `your_table`
FOR EACH ROW
BEGIN
    DECLARE original_query VARCHAR(1024);
    SET original_query = (SELECT info FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id = CONNECTION_ID());
    INSERT INTO `app_sql_debug_log`(`query`) VALUES (original_query);
END;
|
DELIMITER ;

您必须创建两个触发器 - 一个用于更新,另一个用于插入。触发器将新查询作为字符串插入 app_sql_debug_log 列的 query 表中。

答案 1 :(得分:4)

我认为您需要检查数据库服务器的General Query Log

The server ... ... logs each SQL statement received from clients. ... ... Since MySQL 5.1.6 log can be a file or a table.

答案 2 :(得分:1)

您不必将其记录到数据库中。

使用file_put_contents with FILE_APPEND并使用制表符分隔符或csv将其存储在文本文件中。这样,您可以在需要时轻松导入数据库或在需要时在Excel或Numbers(在Mac中)查看文件。

您可以按日期记录文本文件,即sql_queries_2012-05-24,并将其存储在一个文件夹中。文本文件不应占用比将其存储在数据库中更多的空间。使用php日期函数的简单'if else'语句应该按日期排序日志。

使用文本文件在资源方面比将它们存储在数据库中更具成本效益。 此外,使用php fgetcsv从文本文件中索引和INSERT比使用mysql UPDATE快得多。

答案 3 :(得分:0)

如果您既不能修改应用程序来记录发送给MySQL的内容(通常是解决方案#1),也不能启用常规查询日志(解决方案#2,但是,不是生产) - 您可能想要使用MySQL代理。请参阅:https://github.com/mysql/mysql-proxy

MySQL Proxy是一个轻量级程序,可以放在客户端(PHP脚本)和MySQL服务器之间。您可以在运行MySQL服务器本身的同一服务器上运行MySQL Proxy,并使您的客户端直接连接到代理端口而不是MySQL服务器(如果您无法修改客户端,您可以将MySQL服务器移动到另一个端口,并设置MySQL代理到以前由MySQL服务器使用的端口)。

然后,可以使用自定义脚本扩展MySQL代理,其中您的自定义脚本可以捕获各种类型的事件:新连接,发送到服务器的查询等。对于查询,您可以灵活地记录它们或阻止它们,或者无论如何,修改查询,或添加除实际发送的查询之外的新查询。

坏消息 - 自定义脚本在Lua http://dev.mysql.com/doc/refman/5.5/en/mysql-proxy-scripting.html中实现。好消息 - 您可以找到许多用于MySQL代理的示例Lua脚本。例如: http://forge.mysql.com/wiki/Lua_Scripts_For_MySQL_Proxy_Examples 。特别是您可能需要检查“阻止不需要的查询”示例并根据您的需要进行修改(您实际上不会阻止任何内容,但会将某些查询打印到日志中)。

MySQL代理增加了一些开销,但通常它非常轻量级。如果你保持你的Lua脚本也很轻松 - 它应该可以正常工作。

修改

存储库最后一次更新于2014年,目前,version archives说明了这一点:

MySQL代理不是GA,不建议用于生产。

我们建议使用MySQL路由器进行生产。 Download MySQL Router »

MySQL路由器看起来不像它允许与MySQL代理相同的功能。

答案 4 :(得分:0)

简单的基于PHP的解决方案

在PHP中使用override_function使用您自己的函数覆盖mysql_query,您可以使用该函数来分析和/或记录任何相关查询。

rename_function('mysql_query', 'mysql_query_orig');
override_function('mysql_query', '$query', 'return override_mysql_query($query);');

function override_mysql_query($query)
{
    $result = mysql_query_orig($query);

    if (stripos($query, "mytablename") !== FALSE) {
        // log, echo, etc.
    }

    return $result;
}

答案 5 :(得分:0)

如果您不希望数据库中缺少某些值,可以使用约束来强制执行该操作吗?

答案 6 :(得分:-1)

如果您的服务器安装了PHP 5.3.0或更高版本,那么这可能会有所帮助 http://www.php.net/manual/en/mysqlnd.plugin.php

答案 7 :(得分:-1)

您可能希望启用binary logging,以便查看每次更新(请注意:并非每个查询)。您只需添加--log-bin选项,然后使用mysqlbinlog查看生成的日志。如有必要,您可以从备份启动数据库的副本,从备份位置的日志开始(使用--master-data选项保存在备份中mysqldump),然后运行一次更新一次,直到你得到一个坏行。然后你知道哪个更新是罪魁祸首。您可以编写最后一部分的脚本和/或在日志长度上使用二进制搜索,以使其更快。