2012-05-17 21 views
17

Hai bisogno di aiuto con MySQL perché non è proprio il mio forte. Quindi ogni aiuto è apprezzato.Ottieni Full MySQL Query String su Insert o Update

Ho problemi sul mio sito in cui UPDATE o INSERT sono stati eseguiti con valori mancanti. Ciò ha causato alcuni problemi su altre funzioni del sito, ma non sono in grado di trovare dove sono stati eseguiti i valori UPDATE o INSERT in una delle classi.

C'è un modo, forse un trigger MySQL, che potrei aggiungere a queste tabelle che mi consentirebbe di memorizzare la query originale o completa dello UPDATE o INSERT. Ho provato la registrazione ma ciò si applica all'intero database e occupa troppo spazio su disco.

Grazie in anticipo per eventuali risposte.

PS: Al momento, le classi PHP sono un po 'sporche dato che siamo ancora in fase di sviluppo, quindi aggiungere le eccezioni alle funzioni di aggiornamento o inserimento richiederà troppo tempo. Quindi concentrati sulla risposta alla domanda. Grazie ancora.

+1

a meno che non vediamo alcuni codice e errore sono sicuro che non saremo in grado di fornire molto aiuto. Quindi, per favore pubblica il tuo codice/errore – Satya

+0

Satya @ L'errore non è legato a MySQL ma più alle nostre classi PHP di base. Quindi non è rilevante. Sto solo cercando modi per registrare UPDATE o INSERT SQL statement su 2 tabelle nel database. Grazie. – asyadiqin

+1

Che cosa usi dal codice? PHP? Se sì, ti fornirò una soluzione rapida, sporca e perfettamente funzionante. –

risposta

4

Penso che sia necessario controllare il General Query Log del server 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 @ Penso che registri TUTTE le istruzioni SQL sul database e che tu abbia le opzioni per registrarlo in un file o in una tabella . Come ho detto, ho provato questo, ma questo consuma un sacco di spazio su disco quando registra tutto. Sto cercando solo di ottenere le istruzioni SQL se un INSERT o UPDATE è fatto su 2 tabelle piuttosto che l'intero database. Se ho torto, puoi fornirmi un esempio su come ottenere il log di query generale per registrare le istruzioni SQL quando vengono apportate modifiche su 2 tabelle specifiche, ad es. Tabella A e TabellaB – asyadiqin

+3

Questo potrebbe funzionare. Imposta il log di query generale per salvare in un log_table e aggiungi un trigger 'INSERT' che consente solo le query' LIKE '% INSERT%' 'e' LIKE '% tableA%' 'per essere effettivamente inserite nel log_table (quindi tu risparmiare spazio) –

+2

@ypercube - Buona idea! Ma non sono sicuro di quali siano le spese generali. –

-1

Probabilmente si desidera attivare la binary logging in modo da poter guardare ogni aggiornamento (nota: non ogni query). È sufficiente aggiungere l'opzione --log-bin, quindi esaminare il registro risultante utilizzando mysqlbinlog. Se necessario, è possibile avviare una copia del database da un backup, avviare il registro nella posizione del backup (salvato nel backup utilizzando qualcosa come l'opzione --master-data su mysqldump) ed eseguire gli aggiornamenti uno alla volta finché non si fare una brutta fila Quindi sai quale aggiornamento è il colpevole. È possibile creare script per l'ultima parte e/o utilizzare la ricerca binaria sulla lunghezza del registro per farlo andare più veloce.

25

È possibile ottenere la query SQL corrente come una stringa con la seguente dichiarazione:

SELECT info FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id = CONNECTION_ID() 

Quindi quello che dovete fare è creare un TRIGGER che gira su operazioni di inserimento e/o aggiornamento sulla vostra tavola che dovrebbe (i) ottenere SQL corrente e (ii) inserirla in un altro tavolo, in questo modo:

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 ; 

Dovrai creare due trigger: uno per gli aggiornamenti e uno per gli inserti. Il trigger inserisce la nuova query come stringa nella tabella app_sql_debug_log nella colonna query.

+0

Grazie per quello. Essendo un utente novizio MySQL, i due trigger che hai scritto sono pensati per le due tabelle, ad es. Tabella A e Tabella B. Quindi devo aggiungere i trigger per ogni tabella? Scusate se questa domanda sembra sciocca, ma in realtà non faccio mai molto lavoro su MySQL e i trigger sono totalmente nuovi per me. Spero di sentirti. – asyadiqin

+0

Sto provando molto a capire la tabella ELENCO PROCESSI. A questo punto del tempo, non ho fatto nulla sui tavoli. Quello che ho fatto è stato semplicemente INSERIRE un nuovo record, così come UPDATE sulle 2 tabelle, ma quando interrogo la tabella PROCESSLIST, non c'è nulla in quella tabella per mostrare la query che ho appena fatto. Mi sto perdendo qualcosa qui? Grazie ancora. – asyadiqin

+0

I trigger vengono attivati ​​da un solo evento, ad esempio SELECT o DELETE. Nel tuo caso vuoi i trigger per le operazioni INSERT AND UPDATE, quindi devi avere due trigger per ogni tabella, l'uno viene attivato su INSERT e l'altro su istruzioni UPDATE. AVVISO: "PRIMA DI INSERIRE SU your_table'" Modificare la parola chiave INSERT su UPDATE per il secondo trigger. In bocca al lupo! –

1

Non è necessario registrarlo in un database.

Utilizzare file_put_contents with FILE_APPEND e memorizzarlo in un file di testo utilizzando i delimitatori di tabulazione o come csv. In questo modo puoi facilmente importare in un database quando è necessario o visualizzare il file in Excel o Numbers (in Mac) ogni volta che ne hai bisogno.

È possibile registrare il file di testo in base alle date, ad esempio sql_queries_2012-05-24, e memorizzarlo in una cartella. I file di testo non dovrebbero occupare più spazio che archiviarli in un database. Una semplice istruzione "if else", con le funzioni di data php, dovrebbe ottenere la registrazione ordinata per data.

L'utilizzo di file di testo è sicuramente più economico in termini di risorse rispetto all'archiviazione in un database. Inoltre, usare php fgetcsv per indicizzare e INSERIRE da file di testo è molto più veloce dell'utilizzo di mysql UPDATE.

0

Se non è possibile modificare l'applicazione per registrare ciò che si invia a MySQL (normalmente, soluzione n. 1), né è possibile abilitare il registro di query generale (soluzione n. 2, ma sì, non per la produzione): è possibile usa il proxy MySQL. Vedere questo: https://github.com/mysql/mysql-proxy

MySQL Proxy è un programma leggero che è possibile inserire tra il client (script PHP) e il server MySQL. È possibile eseguire MySQL Proxy sullo stesso server in cui si esegue il server MySQL stesso e connettere i client alla porta proxy anziché al server MySQL direttamente (se non è possibile modificare il client, è possibile spostare il server MySQL su un'altra porta e configurare MySQL Proxy alla porta precedentemente utilizzata da MySQL Server).

Quindi, il proxy MySQL può essere esteso con script personalizzati, in cui lo script personalizzato può intercettare vari tipi di eventi: nuove connessioni, query inviate al server, ecc. Per le query si ha la flessibilità di registrarle o bloccarle, oppure modificare la query o aggiungere nuove query oltre a quelle effettivamente inviate, qualunque sia.

Cattive notizie: gli script personalizzati sono implementati in Lua ( http://dev.mysql.com/doc/refman/5.5/en/mysql-proxy-scripting.html) . Buone notizie: puoi trovare molti esempi di script Lua per il proxy MySQL. Ad esempio qui: http://forge.mysql.com/wiki/Lua_Scripts_For_MySQL_Proxy_Examples . In particolare, è possibile selezionare l'esempio "Blocca query indesiderate" e modificarlo in base alle proprie esigenze (in realtà non si bloccherà nulla, ma verranno stampate alcune query nel registro).

MySQL Proxy aggiunge un sovraccarico, ma in generale è piuttosto leggero. Se tieni anche gli script Lua leggeri, dovrebbe funzionare bene.

EDIT:

Il repository è stato aggiornato il 2014, e attualmente, il version archives dire questo:

MySQL Proxy non è GA, e non è raccomandato per l'uso in produzione.

Consigliamo MySQL Router per l'uso di produzione. Download MySQL Router »

MySQL Router non sembra che offra tristemente lo stesso tipo di funzionalità di MySQL Proxy.

0

semplice basato su PHP Soluzione

Usa override_function in PHP di ignorare mysql_query con la propria funzione che è possibile utilizzare al profilo e/o accedere qualsiasi delle query in questione.

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

Se non si desidera alcun valore mancante nel database, è possibile utilizzare il vincolo per applicarlo?

Problemi correlati