Как записывать запросы об ошибках в MySQL? - PullRequest
9 голосов
/ 17 апреля 2010

Я знаю, что есть general_log, в котором регистрируются все запросы, но я хочу выяснить, в каком запросе произошла ошибка, и получить сообщение об ошибке. Я попытался выполнить запрос об ошибке специально, но он регистрируется как обычный запрос и не сообщает об этом с ошибкой. Есть идеи?

Ответы [ 5 ]

7 голосов
/ 26 июля 2011

В MySQL нет функций для этого .

Вам придется придерживаться регистрации на уровне приложений.

3 голосов
/ 07 августа 2015

Можно регистрировать запросы об ошибках с помощью 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 в порядке. Иначе - ошибка.

3 голосов
/ 05 октября 2012

Я знаю, что сейчас это древняя история, но для тех, у кого есть такая же проблема, которая появляется здесь от Google, вот мои два цента

Если вы используете клиент Cli, вы можете просто перенаправить свой sterr в файл, а затем проанализировать его.

mysql -u user -p 2> errors.log
2 голосов
/ 29 сентября 2012

Несмотря на то, что этот вопрос довольно старый, я надеюсь, что он будет полезен для тех, кто искал запросы об ошибках в журнале 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-прокси является бета-версией. Используйте с осторожностью, я думаю.Работаю здесь уже почти полгода без проблем, однако YMMV.

1 голос
/ 17 апреля 2010

Я попытался запустить запрос на ошибку цель, но он регистрируется как обычный запрос и не сообщает об этом с ошибкой. любой идеи?

Итак, вы сделали это неправильно. Никакой другой идеи без кода.

в PHP я делаю это следующим образом (предположим, вы используете драйвер mysql):

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

будет регистрировать все ошибочные запросы, если у вас установлена ​​log_errors (и вы должны)

EDIT: Теперь я вижу, вы хотите протоколирование глобального уровня, а не уровня приложения. Но может вам подойдет и уровень приложения?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...