2010-03-22 12 views
30

Desidero scoprire quali tabelle sono state modificate nell'ultima ora in un database MySQL. Come posso fare questo?Query per trovare tabelle modificate nell'ultima ora

+1

Le tabelle hanno una colonna timestamp quando i dati sono stati modificati? – TomTom

+0

Penso che molti di loro, se non tutti, abbiano un campo "creato". Non sono sicuro che questo risponda alla tua domanda; il database proviene da un sito web che non ho sviluppato ma devo mantenere, quindi sono un po 'perso. –

+0

puoi descrivere l'usecase? potrebbe esserci una soluzione migliore a ciò che si vuole ottenere –

risposta

54

MySQL 5.x può farlo tramite il database INFORMATION_SCHEMA. Questo database contiene informazioni sulle tabelle, viste, colonne, ecc

SELECT * 
FROM `INFORMATION_SCHEMA`.`TABLES` 
WHERE 
    DATE_SUB(NOW(), INTERVAL 1 HOUR) < `UPDATE_TIME` 

restituisce tutti i tavoli che sono stati aggiornati (UPDATE_TIME) nelle ultime ore. Puoi anche filtrare per nome del database (colonna TABLE_SCHEMA).

Una query di esempio:

SELECT 
    CONCAT(`TABLE_SCHEMA`, '.', `TABLE_NAME`) AS `Table`, 
    UPDATE_TIME AS `Updated` 
FROM `INFORMATION_SCHEMA`.`TABLES` 
WHERE 
    DATE_SUB(NOW(), INTERVAL 3 DAY) < `UPDATE_TIME` 
    AND `TABLE_SCHEMA` != 'INFORMATION_SCHEMA' 
    AND `TABLE_TYPE` = 'BASE TABLE'; 
+0

Grazie! Questo fa esattamente quello di cui avevo bisogno –

+0

+1, bel modo per farlo. –

+23

Tieni presente che questo approccio funziona solo con le tabelle MyISAM, non con InnoDB. –

5

Per ogni tabella che si desidera rilevare il cambiamento, è necessario disporre di una colonna che contiene timestamp dell'ultima modifica.

Per ogni inserimento o aggiornamento nella tabella, è necessario aggiornare tale colonna con la data e l'ora correnti.

In alternativa, è possibile impostare uno trigger che aggiorna automaticamente la colonna su ciascun inserto o modifica. In questo modo non devi modificare tutta la tua query.

Una volta che questo funziona, per scoprire se le righe da una tabella sono state modificate nelle ultime ore, eseguire la query

select count(*) from mytable where datemod>subtime(now(),'1:0:0') 

Ripetere l'operazione per ogni tavolo si desidera controllare.

4

InnoDB al momento manca ancora un meccanismo nativo per recuperare queste informazioni. Nel related feature request at MySQL, qualcuno consiglia di impostare i trigger AFTER [all events] su ciascuna tabella da monitorare. Il trigger emetterà una dichiarazione come

INSERT INTO last_update VALUE ('current_table_name', NOW()) 
ON DUPLICATE KEY UPDATE update_time = NOW(); 

in una tabella come questa:

CREATE TABLE last_update (
    table_name VARCHAR(64) PRIMARY KEY, 
    update_time DATETIME 
) ENGINE = MyISAM; -- no need for transactions here 

alternativa, se una leggera inesattezza a questi dati (nell'intervallo di un secondo) è accettabile, e se hai accesso in lettura ai file di dati MySQL, puoi passare a un'impostazione dove inndb_files_per_table = ON (consigliata in ogni caso) e controllare l'ultima ora di modifica dei file di dati sottostanti.

Questi file si trovano in /var/lib/mysql/[database_name]/*.ibd nella maggior parte delle installazioni predefinite.

Nota: se si decide di percorrere questa tratta, è necessario recreate existing tables per la nuova impostazione da applicare.

+0

È possibile utilizzare il tipo di dati TIMESTAMP anziché DATETIME. Definirlo come "' update_time' TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP " ... e verrà impostato automaticamente quando si inseriscono i dati, se omessi. – DustWolf

0
SELECT * 
FROM information_schema.tables 
WHERE UPDATE_TIME >= SYSDATE() - INTERVAL 1 DAY && TABLE_TYPE != 'SYSTEM VIEW' 

SELECT * 
FROM information_schema.tables 
WHERE UPDATE_TIME >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) && TABLE_TYPE != 'SYSTEM VIEW' 
3

ho risposto a una domanda come questa nel DBA StackExchange circa 1,5 anni fa: Fastest way to check if InnoDB table has changed.

Sulla base di quel vecchio risposta, vi consiglio il seguente

Flushing Scrive su disco

Questa è una configurazione di una volta. È necessario impostare innodb_max_dirty_pages_pct su 0.

Innanzitutto, aggiungere a/etc/my.CNF

[mysqld] 
innodb_max_dirty_pages_pct=0 

Poi, eseguire questo per evitare di dover riavviare mysql:

mysql> SET GLOBAL innodb_max_dirty_pages_pct = 0; 

Restituisce un timestamp della tabella InnoDB di .ibd file

ls ha la possibilità di recuperare il timestamp di UNIX in pochi secondi. Per una tabella InnoDB mydb.mytable

$ cd /var/lib/mysql/mydb 
$ ls -l --time-style="+%s" mytable.ibd | awk '{print $6}' 

È quindi possibile calcolare UNIX_TIMESTAMP(NOW()) - (timestamp of the .ibd file) e vedere se è 3600 o meno.

Provalo !!!

+0

Grazie Rolando! Questo è stato molto utile e informativo. – dotancohen

Problemi correlati