Come posso sapere quando è stato aggiornato l'ultima tabella MySQL?


176

Nel piè di pagina della mia pagina, vorrei aggiungere qualcosa come "ultimo aggiornamento di xx / xx / 200x" con questa data che è l'ultima volta che una certa tabella mySQL è stata aggiornata.

Qual è il modo migliore per farlo? Esiste una funzione per recuperare la data dell'ultimo aggiornamento? Devo accedere al database ogni volta che ho bisogno di questo valore?


Risposte:


276

Nelle versioni successive di MySQL è possibile utilizzare il information_schemadatabase per indicare quando è stata aggiornata un'altra tabella:

SELECT UPDATE_TIME
FROM   information_schema.tables
WHERE  TABLE_SCHEMA = 'dbname'
   AND TABLE_NAME = 'tabname'

Ciò significa ovviamente aprire una connessione al database.


Un'opzione alternativa sarebbe quella di "toccare" un determinato file ogni volta che la tabella MySQL viene aggiornata:

Sugli aggiornamenti del database:

  • Apri il tuo file timestamp in O_RDRWmodalità
  • close nuovamente

o in alternativa

  • utilizzare touch(), l'equivalente PHP della utimes()funzione, per modificare il timestamp del file.

Sulla pagina di visualizzazione:

  • utilizzare stat()per rileggere il tempo di modifica del file.

9
Per i dettagli, comprese le limitazioni di InnoDB, consultare dev.mysql.com/doc/refman/5.5/en/show-table-status.html ( show table statususi information_schema.tables)
KCD,

11
Sia il UPDATE_TIMEmetodo che il show table statusmetodo seguente sono disponibili solo con il motore MyISAM, non InnoDB. Sebbene questo sia elencato come un bug , è menzionato nel riferimento MySQL 5.5 , che afferma anche che la file_per_tablemodalità è un indicatore inaffidabile del tempo di modifica.
idoimaging

5
Ancora una volta, non funziona su InnoDB perché mysql è f ** king buggy: bugs.mysql.com/bug.php?id=14374
TMS

7
Per MySQL 5.7.2+ funziona anche con InnoDB : "A partire da MySQL 5.7.2, UPDATE_TIME visualizza un valore data / ora per l'ultimo UPDATE, INSERT o DELETE eseguito su tabelle InnoDB che non sono partizionate. In precedenza, UPDATE_TIME visualizzava un valore NULL per le tabelle InnoDB. "
Peter V. Mørch,

2
Questo non sembra persistere al riavvio per me (sulla versione 5.7.11).

58

Non ho un database information_schema, usando mysql versione 4.1.16, quindi in questo caso puoi interrogare questo:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Restituirà queste colonne:

| Nome | Motore | Versione | Row_format | Righe | Avg_row_length 
| Data_length | Max_data_length | Index_length | Data_free | Auto_increment
| Create_time | Update_time | Check_time | Collazione
| Checksum | Crea_opzioni | Commento |

Come puoi vedere c'è una colonna chiamata: " Update_time " che mostra l'ultimo orario di aggiornamento per your_table .


2
Funziona anche più velocemente (4x)
dell'istruzione

1
In effetti, la maggior parte dei comandi SHOW come questo sono semplicemente mappati internamente alle query Information_schema, quindi questa risposta fornisce esattamente gli stessi dati della risposta di Alnitak sopra. E ajacian81 è corretto: non funziona per il motore di archiviazione predefinito di MySQL, InnoDB.
Bill Karwin,

56

Sono sorpreso che nessuno abbia suggerito di tenere traccia dell'ultimo aggiornamento per riga:

mysql> CREATE TABLE foo (
  id INT PRIMARY KEY
  x INT,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
                     ON UPDATE CURRENT_TIMESTAMP,
  KEY (updated_at)
);

mysql> INSERT INTO foo VALUES (1, NOW() - INTERVAL 3 DAY), (2, NOW());

mysql> SELECT * FROM foo;
+----+------+---------------------+
| id | x    | updated_at          |
+----+------+---------------------+
|  1 | NULL | 2013-08-18 03:26:28 |
|  2 | NULL | 2013-08-21 03:26:28 |
+----+------+---------------------+

mysql> UPDATE foo SET x = 1234 WHERE id = 1;

Questo aggiorna il timestamp anche se non l'abbiamo menzionato nell'aggiornamento.

mysql> SELECT * FROM foo;
+----+------+---------------------+
| id | x    | updated_at          |
+----+------+---------------------+
|  1 | 1235 | 2013-08-21 03:30:20 | <-- this row has been updated
|  2 | NULL | 2013-08-21 03:26:28 |
+----+------+---------------------+

Ora puoi eseguire una query per MAX ():

mysql> SELECT MAX(updated_at) FROM foo;
+---------------------+
| MAX(updated_at)     |
+---------------------+
| 2013-08-21 03:30:20 |
+---------------------+

Certamente, ciò richiede più spazio di archiviazione (4 byte per riga per TIMESTAMP).
Ma questo funziona per le tabelle InnoDB precedenti alla versione 5.7.15 di MySQL, che INFORMATION_SCHEMA.TABLES.UPDATE_TIMEnon funziona.


10
+1 Per quanto mi riguarda, questa è l'unica risposta giusta a questa domanda. La domanda vuole davvero sapere quando vengono aggiornati i dati rilevanti e non quando una tabella (che è irrilevante per l'utente) può o non può essere stata modificata per qualsiasi motivo.
siride,

23
Ma se si elimina un record con un tempo di aggiornamento inferiore, MAX (updated_at) non funzionerà.
Ammamon,

3
@Ammamon, vero, se devi anche tenere conto delle eliminazioni, questa soluzione non riflette questo. Un trigger per l'aggiornamento di una tabella di riepilogo potrebbe essere l'unica soluzione completa, ma ciò creerebbe un collo di bottiglia.
Bill Karwin,

2
per la maggior parte dei casi sapere che la cancellazione non sarebbe altrettanto rilevante, e molti aps di livello superiore non cancellano veramente da molte tabelle ma semplicemente annullano un flag per l'equivalente.
Samuel Fullman,

1
@Pavan, non c'è alcuna differenza, ti affidi solo al comportamento predefinito e il mio esempio spiega esplicitamente l'opzione. Ma l'opzione è identica al comportamento predefinito.
Bill Karwin,

13

La cosa più semplice sarebbe controllare il timestamp dei file della tabella sul disco. Ad esempio, è possibile controllare nella directory dei dati

cd /var/lib/mysql/<mydatabase>
ls -lhtr *.ibd

Questo dovrebbe darti l'elenco di tutte le tabelle con la tabella quando è stata modificata l'ultima volta l'ultima volta, prima.


Davvero un'ottima risposta poiché UPDATE_TIME è NULL per tutte le tabelle nel mio caso (MariaDb)
Alexander Vasiljev

I file ibd memorizzano solo la struttura della tabella. Per impostazione predefinita, i dati sono memorizzati in ibdata1 in modo che il timestamp del file ibd non si aggiorni quando i dati vengono modificati nella tabella. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow

@StackUnderflow, Quello che hai detto non è accurato. I file ibd memorizzano dati e indici per un tablespace, che contiene una o più tabelle. Se i dati sono memorizzati in ibdata1, non ci sarà alcun file ibd. La memorizzazione dei dati in un file per tabella è stata l'impostazione predefinita da MySQL 5.6 nel 2013.
Bill Karwin

7

Per un elenco delle recenti modifiche alla tabella, utilizzare questo:

SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME

3
Perché tutti i miei UPDATE_TIMEsono null? Qualche idea?
Metafaniel,

5
UPDATE_TIME è null perché stai usando InnoDB invece di MyISAM. InnoDB è generalmente la scelta migliore, ma non supporta UPDATE_TIME.
Xaraxia,

5

Vorrei creare un trigger che intercetta tutti gli aggiornamenti / inserimenti / eliminazioni e scrivere il timestamp nella tabella personalizzata, qualcosa come tablename | timestamp

Solo perché non mi piace l'idea di leggere direttamente le tabelle di sistema interne del server db


1
Questa sembra una buona soluzione per MS SQL, perché non esiste una UPDATE_TIMEcolonna come in MySQL.
Darcy,

3

Sebbene ci sia una risposta accettata, non penso che sia quella giusta. È il modo più semplice per ottenere ciò che è necessario, ma anche se già abilitato in InnoDB (in realtà i documenti ti dicono che dovresti comunque ottenere NULL ...), se leggi i documenti MySQL , anche nella versione corrente (8.0) usando UPDATE_TIME è non è l'opzione giusta, perché:

I timestamp non persistono quando il server viene riavviato o quando la tabella viene eliminata dalla cache del dizionario dei dati InnoDB.

Se capisco correttamente (non riesco a verificarlo su un server in questo momento), il timestamp viene resettato dopo il riavvio del server.

Per quanto riguarda le soluzioni reali (e, beh, costose), hai la soluzione di Bill Karwin con CURRENT_TIMESTAMP e mi piacerebbe proporne una diversa, che si basa su trigger (sto usando quella).

Si inizia creando una tabella separata (o forse si dispone di un'altra tabella che può essere utilizzata per questo scopo) che funzionerà come una memoria per le variabili globali (qui i timestamp). Devi archiviare due campi: il nome della tabella (o qualunque valore desideri conservare qui come ID tabella) e il timestamp. Dopo averlo, dovresti inizializzarlo con questo ID tabella + data di inizio (NOW () è una buona scelta :)).

Ora, passi alle tabelle che desideri osservare e aggiungi i trigger DOPO INSERIRE / AGGIORNA / ELIMINA con questa o una procedura simile:

CREATE PROCEDURE `timestamp_update` ()
BEGIN
    UPDATE `SCHEMA_NAME`.`TIMESTAMPS_TABLE_NAME`
    SET `timestamp_column`=DATE_FORMAT(NOW(), '%Y-%m-%d %T')
    WHERE `table_name_column`='TABLE_NAME';
END

1

Analisi a livello di sistema operativo:

Trova dove è archiviato il DB sul disco:

grep datadir /etc/my.cnf
datadir=/var/lib/mysql

Controlla le modifiche più recenti

cd /var/lib/mysql/{db_name}
ls -lrt

Dovrebbe funzionare su tutti i tipi di database.


0

Basta prendere la data del file modificata dal file system. Nella mia lingua che è:

 tbl_updated = file.update_time(
        "C:\ProgramData\MySQL\MySQL Server 5.5\data\mydb\person.frm")

Produzione:

1/25/2013 06:04:10 AM

6
sembra un hack altamente non portatile, un modo standard che funzionerebbe ovunque sarebbe meglio
Tejesh Alimilli

0

Se usi Linux puoi usare inotify per guardare la tabella o la directory del database. inotify è disponibile da PHP, node.js, perl e sospetto che la maggior parte delle altre lingue. Ovviamente devi aver installato inotify o averlo installato dal tuo ISP. Molti ISP non lo faranno.


2
I controlli del filesystem non sono utili se il database è in esecuzione su un server separato
Sam Dufel,

0

Non sono sicuro se questo sarebbe di qualche interesse. L'utilizzo di mysqlproxy tra mysql e client e l'utilizzo di uno script lua per aggiornare un valore chiave in memcached in base alle interessanti modifiche alla tabella UPDATE, DELETE, INSERT è stata la soluzione che ho fatto abbastanza di recente. Se il wrapper supportasse hook o trigger in php, questo avrebbe potuto essere più appetibile. Nessuno dei wrapper per ora lo fa.


0

ho creato una colonna per nome: update-at in phpMyAdmin e ho ottenuto l'ora corrente dal metodo Date () nel mio codice (nodejs). ad ogni modifica della tabella questa colonna contiene l'ora delle modifiche.


1
Benvenuto in StackOverflow! Si prega di modificare la risposta per includere una parte del codice è stato utilizzato, così come una spiegazione del motivo per cui si è scelto di fare in questo modo. Questa domanda ha quasi undici anni e ha già una risposta accettata e ben votata. La tua risposta, senza un codice o una spiegazione, sarà probabilmente ridotta o eliminata. Modificarlo per includere quelle cose aiuterà a giustificare il suo posto in questo post.
Das_Geek,

0

a) Ti mostrerà tutte le tabelle e le date dell'ultimo aggiornamento

SHOW TABLE STATUS FROM db_name;

quindi, è possibile inoltre richiedere una tabella specifica:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Come negli esempi precedenti, non è possibile utilizzare l'ordinamento su "Update_time", ma utilizzando SELECT è possibile:

SELECT * FROM information_schema.tables WHERE TABLE_SCHEMA='db_name' ORDER BY UPDATE_TIME DESC;

per chiedere ulteriori informazioni su una tabella particolare:

SELECT * FROM information_schema.tables WHERE TABLE_SCHEMA='db_name' AND table_name='table_name' ORDER BY UPDATE_TIME DESC';

-1

Questo è quello che ho fatto, spero che aiuti.

<?php
    mysql_connect("localhost", "USER", "PASSWORD") or die(mysql_error());
    mysql_select_db("information_schema") or die(mysql_error());
    $query1 = "SELECT `UPDATE_TIME` FROM `TABLES` WHERE
        `TABLE_SCHEMA` LIKE 'DataBaseName' AND `TABLE_NAME` LIKE 'TableName'";
    $result1 = mysql_query($query1) or die(mysql_error());
    while($row = mysql_fetch_array($result1)) {
        echo "<strong>1r tr.: </strong>".$row['UPDATE_TIME'];
    }
?>

2
Perché dovresti usare come qui?
Kyle Buser,

3
@WesleyMurch: il tag <font> è deprecato.
siride,

-9

Memorizza la query in una variabile globale quando non è disponibile.

Creare una pagina Web per forzare la ricarica della cache quando la si aggiorna.

Aggiungi una chiamata alla pagina di ricarica negli script di distribuzione.


2
non è possibile "memorizzare nella cache" le variabili tra invocazioni indipendenti di una pagina PHP senza assistenza esterna.
Alnitak,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.