2012-05-17 2 views
17

Нужна помощь с MySQL, так как это не моя сильная сторона. Поэтому любая помощь приветствуется.Получить полную строку запроса MySQL на вставку или обновление

У меня есть проблемы на моем сайте, где UPDATE или INSERT были выполнены с отсутствующими значениями. Это вызвало некоторые проблемы с другими функциями на сайте, но я не смог найти, где были сделаны UPDATE или INSERT в любом из классов.

Есть ли способ, возможно, триггер MySQL, который я мог бы добавить к этим таблицам, что позволило бы мне сохранить исходный или полный запрос UPDATE или INSERT. Я попытался войти в систему, но это относится ко всей базе данных, и она занимает слишком много дискового пространства.

Заранее благодарим за любые ответы.

PS: На данный момент классы PHP немного запутаны, поскольку мы все еще находимся на стадии разработки, поэтому добавление исключений из функций обновлений или вставок займет слишком много времени. Поэтому, пожалуйста, сосредоточьте свой ответ на вопросе. Еще раз спасибо.

+1

, если мы не видим код и ошибку. Я уверен, что мы не сможем оказать большую помощь. Итак, отправьте свой код/​​ошибку – Satya

+0

Satya @ Ошибка связана не с MySQL, а с другими основными классами PHP. Так что это не актуально. Я просто ищу способы зарегистрировать инструкцию UPDATE или INSERT SQL на 2 таблицы в базе данных. Благодарю. – asyadiqin

+1

Что вы используете на стороне кода? PHP? Если да, я предоставлю вам быстрое, грязное и полностью работающее решение. –

ответ

4

Я думаю, вам нужно проверить General Query Log вашего сервера db.

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 в базе данных, и у вас есть возможность либо зарегистрировать его в файле или таблице , Как я уже говорил, я пробовал это, но это потребляет много дискового пространства, поскольку он регистрирует все. Я рассматриваю только получение операторов SQL, если INSERT или UPDATE выполняется на 2 таблицах, а не на всей базе данных. Если я ошибаюсь, можете ли вы представить мне пример того, как заставить журнал общих запросов регистрировать SQL-запросы, когда изменения производятся на двух конкретных таблицах, например. TableA и TableB – asyadiqin

+3

Это может сработать. Установите общий журнал запросов для сохранения в лог-таблицу и добавьте триггер '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, который работает на вставных и/или операций обновления на вашем столе который должен (я) получить текущую инструкцию SQL и (б) вставить его в другую таблицу, например, так:

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.

+0

Спасибо за это. Будучи пользователем новичка MySQL, два триггера, которые вы написали, предназначены для двух таблиц, например. TableA и TableB. Итак, чтобы добавить триггеры для каждой таблицы? Извините, если этот вопрос звучит глупо, но я на самом деле не очень много работаю над MySQL, и триггеры для меня совершенно новые. Надеюсь услышать вас снова. – asyadiqin

+0

Я очень стараюсь понять таблицу PROCESSLIST. На данный момент я ничего не сделал на столах. Я сделал просто INSERT новую запись, а также 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 if с функциями php date должен получить регистрацию, отсортированную по датам.

Использование текстовых файлов, безусловно, более экономично в ресурсах, чем хранение их в базе данных. Кроме того, использование php fgetcsv для индексирования и INSERT из текстовых файлов намного быстрее, чем при использовании mysql UPDATE.

0

Если вы не можете изменить приложение для регистрации того, что вы отправляете в MySQL (обычно, решение № 1), и вы не можете включить общий журнал запросов (решение # 2, но да, а не для производства) - вы можете захотеть используйте MySQL Proxy. См. Это: https://github.com/mysql/mysql-proxy

MySQL Proxy - это легкая программа, которую вы можете установить между вашим клиентом (скрипты PHP) и сервером MySQL. Вы можете запустить MySQL Proxy на том же сервере, на котором вы запускаете сам сервер MySQL, и заставлять своих клиентов напрямую подключаться к прокси-порту вместо сервера MySQL (если вы не можете изменить клиент, вы можете переместить сервер MySQL на другой порт и настроить MySQL Proxy к порту, ранее используемому MySQL Server).

Затем прокси MySQL можно расширить с помощью специальных скриптов, где ваш собственный скрипт может захватывать различные типы событий: новые подключения, запросы, отправленные на сервер, и т. Д. Для запросов вы имеете возможность регистрировать их или блокировать, или изменить запрос, или добавить новые запросы в дополнение к тем, которые действительно отправлены, что угодно.

Плохие новости - пользовательские скрипты реализованы в Lua ( http://dev.mysql.com/doc/refman/5.5/en/mysql-proxy-scripting.html) . Хорошие новости - вы можете найти множество образцов сценариев Lua для прокси-сервера MySQL. Например: http://forge.mysql.com/wiki/Lua_Scripts_For_MySQL_Proxy_Examples . В частности, вы можете захотеть проверить пример «Блокировать нежелательные запросы» и изменить его на свои нужды (вы фактически ничего не блокируете, а будете печатать определенные запросы в журнале).

MySQL Proxy добавляет некоторые накладные расходы, но в целом он довольно легкий. Если вы также сохраните свои сценарии Lua, это должно сработать.

EDIT:

Репозиторий был актуализирован 2014, и в настоящее время, то version archives сказать:

MySQL Proxy не GA, и не рекомендуется для использования в производстве.

Мы рекомендуем использовать MySQL-маршрутизатор для использования в производстве. Download MySQL Router »

MySQL-маршрутизатор не похож на то, что он допускает такую ​​же функциональность, как MySQL Proxy, к сожалению.

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

Если вы не хотите, чтобы в базе данных отсутствовало какое-либо значение, можете ли вы использовать ограничение для обеспечения этого?

Смежные вопросы