如何在mysql中记录错误查询?

时间:2010-04-17 13:55:53

标签: mysql linux logging

我知道有general_log记录所有查询,但我想找出哪个查询有错误,并获取错误消息。我试图故意运行错误查询,但它记录为普通查询,并且不报告错误。有任何想法吗?

6 个答案:

答案 0 :(得分:7)

There is no functionality in MySQL to do this

您必须坚持使用应用程序层日志记录。

答案 1 :(得分:3)

我知道现在这已经很古老了,但是对于那些从谷歌这里出现同样问题的人来说,这是我的两分钱。

如果你正在使用cli客户端,你可以简单地将你的sterr重定向到一个文件,然后解析它。

mysql -u user -p 2> errors.log

答案 2 :(得分:3)

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

  

MariaDB Audit Plugin适用于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是好的。否则 - 错误。

答案 3 :(得分:2)

即使这个问题很老,我希望对搜索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,调整somedbmysql_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。

答案 4 :(得分:1)

  

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

所以,你做错了。没有代码就没有其他想法。

PHP中的

我这样做(假设你使用的是mysql驱动程序):

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

如果您设置log_errors设置,则会记录所有错误的查询

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

答案 5 :(得分:0)

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