2012-05-17 40 views
17

需要MySQL帮助,因为它不是我的特长。所以,任何帮助表示赞赏。在插入或更新时获取完整的MySQL查询字符串

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

是否有任何方式,也许是MySQL触发器,我可以添加到这些表,这将允许我存储UPDATEINSERT的原始或完整查询。我尝试过日志记录,但这适用于整个数据库,并占用了太多的磁盘空间。

在此先感谢您的答复。 PS:现在,由于我们仍处于开发阶段,所以PHP类有点麻烦,所以在更新或插入函数中添加例外将花费太多时间。所以请把答案集中在这个问题上。再次感谢。

+1

除非我们看到一些代码和错误,我相信我们无法提供很多帮助。所以,请发布你的代码/错误 – Satya

+0

Satya @这个错误与MySQL无关,但更多关于我们的核心PHP类。所以它不相关。我正在寻找方法来记录UPDATE或INSERT SQL语句在数据库中的两个表上。谢谢。 – asyadiqin

+1

你在代码方面使用什么? PHP?如果是的话,我会为您提供一个快速,肮脏和完全可行的解决方案。 –

回答

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.

+0

Ravinder @我认为它会记录数据库上的所有SQL语句,并且您可以选择将它们记录到表中的文件中。正如我所提到的,我已经尝试了这一点,但这会消耗大量的磁盘空间,因为它记录了所有内容。我正在查看如果在2个表上而不是整个数据库上完成INSERT或UPDATE,只是获取SQL语句。 如果我错了,请给我一个例子,说明如何在2个特定的表格上进行更改时,如何让通用查询日志记录SQL语句,例如。表A和表B – asyadiqin

+3

这可以工作。将通用查询日志设置为保存到log_table中,并添加一个“INSERT”触发器,该触发器只允许LIKE'%INSERT%'和'LIKE'%tableA%''查询被插入到log_table中节省空间) –

+2

@ypercube - 好主意!但不知道什么是管理费用。 –

-1

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

25

你可以得到当前的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 ; 

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

+0

谢谢你。作为MySQL新手用户,你写的两个触发器是否适用于两个表格,例如。表A和表B。所以我ahev添加每个表的触发器?对不起,如果这个问题听起来很愚蠢,但我从来没有在MySQL上做过很多工作,触发器对我来说是全新的。希望能从你那听到答复。 – asyadiqin

+0

我正在努力了解表PROCESSLIST。在这个时候,我没有在桌上做任何事情。我所做的只是插入一条新记录,以及对两个表的UPDATE,但是当我查询表PROCESSLIST时,表中没有任何内容显示我刚刚做的查询。我在这里错过了什么吗?再次感谢。 – asyadiqin

+0

触发器仅由一个事件触发 - 例如SELECT或DELETE。在你的情况下,你需要INSERT AND UPDATE操作的触发器,所以你必须为每个表有两个触发器,一个在INSERT触发,另一个在UPDATE语句触发。注意:“在插入'your_table'之前”将第二个触发器的INSERT关键字更改为UPDATE。祝你好运! –

1

您并不完全必须将其记录到数据库中。

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

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

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

0

如果您既不能修改应用程序以记录您发送给MySQL的内容(通常是解决方案#1),也不能启用通用查询日志(解决方案2,但是,不是用于生产) - 您可能希望使用MySQL代理。看到这个:https://github.com/mysql/mysql-proxy

MySQL代理是轻量级的程序,你可以放在你的客户端(PHP脚本)和MySQL服务器之间。您可以在运行MySQL服务器的同一台服务器上运行MySQL代理,并让您的客户端直接连接到代理端口而不是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 Proxy增加了一些开销,但通常它非常轻量级。如果你保持你的Lua脚本也很轻松 - 它应该可以正常工作。

编辑:

信息库最后更新于2014年,目前,该version archives这样说:

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

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

MySQL路由器看起来并不像MySQL许可证那样可悲地使用同样的功能。

0

简单的基于PHP的解决方案

使用override_function在PHP重写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; 
} 
0

如果你不想在数据库中丢失一些值,你可以使用约束来强制执行吗?