【问题标题】:How to log error queries in mysql?如何在mysql中记录错误查询?
【发布时间】:2011-02-09 03:45:25
【问题描述】:

我知道有记录所有查询的general_log,但我想找出哪个查询有错误,并得到错误消息。我曾尝试故意运行错误查询,但它记录为正常查询并且不会报告错误。有任何想法吗?

【问题讨论】:

    标签: mysql linux logging


    【解决方案1】:

    我尝试过运行错误查询 目的,但它记录为普通查询 并且不会报告错误。任何 想法?

    所以,你做错了。没有代码就别想了。

    在 PHP 中我是这样做的(假设您使用的是 mysql 驱动程序):

    $res=mysql_query($sql) or trigger_error(mysql_error().$sql);
    

    如果您设置了log_errors(并且您必须这样做),它将记录所有错误查询

    编辑: 我现在看到,您想要全局级别的日志记录,而不是应用程序级别。 但可能应用级别也适合您?

    【讨论】:

    • 我通过 phpmyadmin 3.3.2 输入 sql 他们做错了吗?
    • @user phpmyadmin 是单用户应用程序,因此不需要任何日志记录。
    • trigger_error 是写入 mysql 日志还是 php 日志?因为我也有使用 mysql 的 shell 脚本。
    • @user 这是 php 指令。它正在写入标准 PHP 错误日志。
    • 感谢回答,但没有解决我的问题,这是依赖于 php 的。
    【解决方案2】:

    There is no functionality in MySQL to do this.

    您将不得不坚持使用应用层日志记录。

    【讨论】:

    • 为什么?一个问题——为什么?做起来太难了吗?只需在将查询和错误扔回客户端时记录它..
    • @Serge:我不知道。似乎实现起来应该不会太难。也许是一个关注点分离的事情(即,让 SQL 语句正确是客户的责任,并且可以随意记录失败)。
    【解决方案3】:

    尽管这个问题已经很老了,但我希望它对搜索 mysql 日志错误查询或类似术语的人有用。

    不久前,我还要求 mysqld 只记录错误查询。我发现 mysql-proxy 可以让你做到这一点,并编写了一个小 LUA 脚本:

    local err_flag = false
    function read_query( packet )
        if packet:byte() == proxy.COM_QUERY then
            local user = proxy.connection.client.username
            local host = proxy.connection.client.src.name
            if user:lower() == 'someuser' then -- change this to any condition where errors should be logged
                proxy.queries:append(1, packet, {resultset_is_needed = true})
                proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SET @last_query = '" .. string.sub(packet, 2) .. "'", {resultset_is_needed = true} )
                proxy.queries:append(3, string.char(proxy.COM_QUERY) .. "SHOW WARNINGS", {resultset_is_needed = true} )
            end
            return proxy.PROXY_SEND_QUERY
        end
    end
    
    
    function insert_query(err_t, err_n, err_m)
      local query = "INSERT INTO `somedb`.`mysql_error` " .. -- change log destination 
        "(`date`, `err_num`,`err_type`, `err_message`, `problem_query`, `conn_id`)" ..
        " VALUES ( NOW(), " ..
        err_n  ..  "," .. "\"" ..
        err_t .."\"" .. "," .. "\"" ..
        err_m .. "\"" .. "," ..
        "@last_query" .. "," ..
        proxy.connection.server.thread_id .. ")"
        proxy.queries:append(4, string.char(proxy.COM_QUERY) .. query, {resultset_is_needed = true})
        return proxy.PROXY_SEND_QUERY
    end
    
    
    function read_query_result(inj)
        local res = assert(inj.resultset)
        if inj.id == 1 then
            err_flag = false
            if res.query_status == proxy.MYSQLD_PACKET_ERR then
                err_flag = true
                return proxy.PROXY_IGNORE_RESULT
            end
        elseif inj.id == 2 then
            return proxy.PROXY_IGNORE_RESULT
        elseif inj.id == 3 then
            if err_flag == true then
                for row in res.rows do
                    proxy.response.type = proxy.MYSQLD_PACKET_ERR
                    proxy.response.errmsg = row[3]
                    insert_query(row[1], row[2], row[3])
                end
                return proxy.PROXY_SEND_RESULT
            end
            return proxy.PROXY_IGNORE_RESULT
        elseif inj.id == 4 then
            return proxy.PROXY_IGNORE_RESULT
        end
    end
    

    记录表需要 DDL,调整 somedb.mysql_error 到喜欢,但不要忘记在上面的 LUA 脚本中也这样做。

    CREATE TABLE `somedb`.`mysql_error` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `date` datetime NOT NULL,
        `err_num` smallint(6) NOT NULL,
        `err_type` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
        `err_message` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
        `problem_query` varchar(8000) COLLATE utf8_unicode_ci NOT NULL,
        `conn_id` int(11) NOT NULL,
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
    

    要使用脚本,请运行

    /path/to/mysql-proxy --proxy-lua-script=/path/to/mysql-proxy-log-error-queries.lua

    或者如果失败 (>=v0.9)

    /path/to/mysql-proxy --proxy-lua-script=/path/to/mysql-proxy-log-error-queries.lua --plugins=proxy

    代理默认运行在4040端口,进行测试:

    mysql -u username -p --host=127.0.0.1 --port=4040

    并运行一些错误的 sql。

    当一切似乎都正常时,将应用程序中的端口设置为 4040 而不是实际的 mysqld 端口,并且在数据库级别记录 mysql 错误。

    最后说明:mysql-proxy 是测试版。我猜要谨慎使用。在这里运行了快半年了,但是YMMV没有问题。

    【讨论】:

    • 不错的一个,试了一下,花了一段时间才终于让它工作,但它就像一个魅力。顺便说一句,它甚至不是 beta,它仍然是 alpha。 dev.mysql.com/downloads/mysql-proxy
    • 这不是性能杀手吗?我认为客户端的错误处理会很好
    • 很高兴听到这个消息! :)
    【解决方案4】:

    我知道这已经过时了,但是对于从 Google 来到这里遇到相同问题的任何人,这是我的两分钱。

    如果您使用的是 cli 客户端,您可以简单地将您的 sterr 重定向到一个文件,然后对其进行解析。

    mysql -u user -p 2> errors.log
    

    【讨论】:

    • 谢谢,不知道可以这样做,而不是登录到文件。我改为将其记录到数据库中。干杯。
    【解决方案5】:

    可以使用MariaDB Audit Plugin 记录错误查询。

    MariaDB 审计插件适用于 MariaDB、MySQL 和 Percona Server。

    例如,对于这些查询

    select now();
    select now()+();
    select 9+();
    select 'hello';
    

    日志看起来像这样:

    20150807 23:00:36,mnv-Satellite-L300D,root,localhost,82,377,QUERY,`test`,'select now()
    LIMIT 0, 1000',0
    20150807 23:00:37,mnv-Satellite-L300D,root,localhost,82,379,QUERY,`test`,'select now()+()',1064
    20150807 23:00:37,mnv-Satellite-L300D,root,localhost,82,382,QUERY,`test`,'select 9+()',1064
    20150807 23:00:38,mnv-Satellite-L300D,root,localhost,82,383,QUERY,`test`,'select \'hello\'
    LIMIT 0, 1000',0
    

    最后一列是返回码。 0 没问题。否则 - 错误。

    【解决方案6】:

    MariaDB 可以使用与 mariadb 一起分发的插件 https://mariadb.com/kb/en/sql-error-log-plugin/ 来做到这一点。

    我昨天试过了,效果和宣传的一样。

    只需要运行:

    install plugin SQL_ERROR_LOG soname 'sql_errlog';
    

    并且有错误的查询将转到$datadir/sql_errors.log,这是大多数linux安装在/var/lib/mysql/sql_errors.log上的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      相关资源
      最近更新 更多