Wie kann ich feststellen, wann eine MySQL-Tabelle zuletzt aktualisiert wurde?

176

In der Fußzeile meiner Seite möchte ich etwas wie "Zuletzt aktualisiert xx / xx / 200x" hinzufügen, wobei dieses Datum das letzte Mal ist, dass eine bestimmte mySQL-Tabelle aktualisiert wurde.

Was ist der beste Weg das zu tun? Gibt es eine Funktion zum Abrufen des letzten aktualisierten Datums? Sollte ich jedes Mal auf die Datenbank zugreifen, wenn ich diesen Wert benötige?

Wut
quelle
Siehe auch
Pekka

Antworten:

276

In späteren Versionen von MySQL können Sie die information_schemaDatenbank verwenden, um zu erfahren, wann eine andere Tabelle aktualisiert wurde:

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

Dies bedeutet natürlich, eine Verbindung zur Datenbank herzustellen.


Eine alternative Option wäre, eine bestimmte Datei zu "berühren", wenn die MySQL-Tabelle aktualisiert wird:

Bei Datenbankaktualisierungen:

  • Öffnen Sie Ihre Zeitstempeldatei im O_RDRWModus
  • close es wieder

oder alternativ

  • Verwenden Sie touch()das PHP-Äquivalent der utimes()Funktion, um den Dateizeitstempel zu ändern.

Auf der Seitenanzeige:

  • Verwenden Sie stat()diese Option, um die Änderungszeit der Datei zurückzulesen.
Alnitak
quelle
9
Einzelheiten einschließlich der InnoDB-Einschränkungen finden Sie unter dev.mysql.com/doc/refman/5.5/en/show-table-status.html ( show table statusverwendet information_schema.tables)
KCD
11
Sowohl die UPDATE_TIMEMethode als auch die folgende show table statusMethode sind nur mit der MyISAM-Engine verfügbar, nicht mit InnoDB. Obwohl dies als Fehler aufgeführt ist , wird es in der MySQL 5.5-Referenz erwähnt , die auch besagt, dass der file_per_tableModus ein unzuverlässiger Indikator für die Änderungszeit ist.
Idoimaging
5
Auch hier funktioniert InnoDB nicht, da MySQL ein verdammter
TMS
7
Für MySQL 5.7.2+ funktioniert es auch für InnoDB : "Ab MySQL 5.7.2 zeigt UPDATE_TIME einen Zeitstempelwert für das letzte UPDATE, INSERT oder DELETE an, das für nicht partitionierte InnoDB-Tabellen ausgeführt wurde. Bisher zeigte UPDATE_TIME einen NULL-Wert an für InnoDB-Tabellen. "
Peter V. Mørch
2
Dies scheint beim Neustart für mich (in Version 5.7.11) nicht zu bestehen.
58

Ich habe keine information_schema-Datenbank mit MySQL-Version 4.1.16. In diesem Fall können Sie Folgendes abfragen:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Diese Spalten werden zurückgegeben:

| Name | Motor | Version | Zeilenformat | Zeilen | Durchschn ._Länge_Länge 
| Datenlänge | Max_data_length | Indexlänge | Datenfrei | Auto_increment
| Create_time | Update_time | Check_time | Sortierung
| Prüfsumme | Create_options | Kommentar |

Wie Sie sehen können, gibt es eine Spalte mit dem Namen " Update_time ", die Ihnen die letzte Aktualisierungszeit für Ihre_Tabelle anzeigt .

Radu Maris
quelle
2
Es ist auch schneller (4x) als die SELECT-Anweisung
jmav
1
Tatsächlich werden die meisten SHOW-Befehle wie diese einfach intern auf Information_schema-Abfragen abgebildet, sodass diese Antwort genau dieselben Daten enthält wie die Antwort von Alnitak oben. Und ajacian81 ist richtig - es funktioniert nicht für MySQLs Standardspeicher-Engine InnoDB.
Bill Karwin
55

Ich bin überrascht, dass niemand vorgeschlagen hat, die letzte Aktualisierungszeit pro Zeile zu verfolgen:

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;

Dadurch wird der Zeitstempel aktualisiert, obwohl wir ihn im UPDATE nicht erwähnt haben.

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 |
+----+------+---------------------+

Jetzt können Sie nach MAX () fragen:

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

Dies erfordert zwar mehr Speicherplatz (4 Bytes pro Zeile für TIMESTAMP).
Aber das funktioniert für InnoDB - Tabellen vor 5.7.15 Version von MySQL, die INFORMATION_SCHEMA.TABLES.UPDATE_TIMEnicht der Fall ist.

Bill Karwin
quelle
10
+1 Für mich ist dies die einzig richtige Antwort auf diese Frage. Die Frage möchte wirklich wissen, wann relevante Daten aktualisiert werden und nicht, wann eine Tabelle (die für den Benutzer irrelevant ist) aus irgendeinem Grund geändert wurde oder nicht.
Siride
23
Wenn Sie jedoch einen Datensatz mit einer geringeren Aktualisierungszeit löschen, funktioniert MAX (aktualisierte_at) nicht.
Ammamon
3
@Ammamon, stimmt, wenn Sie auch Löschungen berücksichtigen müssen, spiegelt diese Lösung dies nicht wider. Ein Auslöser zum Aktualisieren einer Übersichtstabelle ist möglicherweise die einzige umfassende Lösung, die jedoch zu einem Engpass führen würde.
Bill Karwin
2
In den meisten Fällen wäre das Wissen über das Löschen nicht so relevant, und viele übergeordnete Aps löschen nicht wirklich aus vielen Tabellen, sondern setzen einfach ein Flag für das Äquivalent.
Samuel Fullman
1
@Pavan, es gibt keinen Unterschied, Sie verlassen sich nur auf das Standardverhalten, und in meinem Beispiel wird die Option explizit beschrieben. Die Option ist jedoch identisch mit dem Standardverhalten.
Bill Karwin
13

Am einfachsten wäre es, den Zeitstempel der Tabellendateien auf der Festplatte zu überprüfen. Sie können beispielsweise in Ihrem Datenverzeichnis nachsehen

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

Dies sollte Ihnen die Liste aller Tabellen mit der Tabelle geben, als sie zuletzt zum ältesten Mal zuerst geändert wurde.

user2654744
quelle
Wirklich gute Antwort, da UPDATE_TIME für alle Tabellen in meinem (MariaDb) Fall NULL ist
Alexander Vasiljev
ibd-Dateien speichern nur die Tabellenstruktur. Standardmäßig werden die Daten in ibdata1 gespeichert, sodass der Zeitstempel der ibd-Datei nicht aktualisiert wird, wenn Daten in der Tabelle geändert werden. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow
7

Verwenden Sie Folgendes, um eine Liste der letzten Tabellenänderungen anzuzeigen:

SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME
Francois Bourgeois
quelle
3
Warum sind alle meine UPDATE_TIMEnull? Irgendeine Idee?
Metafaniel
5
Ihr UPDATE_TIME ist null, da Sie InnoDB anstelle von MyISAM verwenden. InnoDB ist im Allgemeinen die bessere Wahl, unterstützt jedoch UPDATE_TIME nicht.
Xaraxia
5

Ich würde einen Trigger erstellen, der alle Aktualisierungen / Einfügungen / Löschungen abfängt und einen Zeitstempel in eine benutzerdefinierte Tabelle schreibt, so etwas wie Tabellenname | Zeitstempel

Nur weil mir die Idee nicht gefällt, interne Systemtabellen des DB-Servers direkt zu lesen

Mikhail
quelle
1
Dies scheint eine gute Lösung für MS SQL zu sein, da es keine UPDATE_TIMESpalte wie in MySQL gibt.
Darcy
3

Obwohl es eine akzeptierte Antwort gibt, glaube ich nicht, dass es die richtige ist. Es ist der einfachste Weg, um das zu erreichen, was benötigt wird, aber selbst wenn es bereits in InnoDB aktiviert ist (tatsächlich sagen Ihnen die Dokumente, dass Sie immer noch NULL erhalten sollten ...), wenn Sie MySQL- Dokumente lesen , ist dies auch in der aktuellen Version (8.0) mit UPDATE_TIME der Fall nicht die richtige Option, weil:

Zeitstempel bleiben nicht erhalten, wenn der Server neu gestartet wird oder wenn die Tabelle aus dem InnoDB-Datenwörterbuch-Cache entfernt wird.

Wenn ich das richtig verstehe (kann es derzeit auf einem Server nicht überprüfen), wird der Zeitstempel nach dem Neustart des Servers zurückgesetzt.

Für echte (und auch kostspielige) Lösungen haben Sie die Lösung von Bill Karwin mit CURRENT_TIMESTAMP und ich möchte eine andere vorschlagen, die auf Triggern basiert (ich verwende diese).

Sie erstellen zunächst eine separate Tabelle (oder haben möglicherweise eine andere Tabelle, die für diesen Zweck verwendet werden kann), die wie ein Speicher für globale Variablen (hier Zeitstempel) funktioniert. Sie müssen zwei Felder speichern - Tabellenname (oder welchen Wert Sie hier als Tabellen-ID behalten möchten) und Zeitstempel. Nachdem Sie es haben, sollten Sie es mit dieser Tabellen-ID + Startdatum initialisieren (NOW () ist eine gute Wahl :)).

Nun wechseln Sie zu Tabellen, die Sie beobachten möchten, und fügen Trigger NACH EINFÜGEN / UPDATE / LÖSCHEN mit diesem oder einem ähnlichen Verfahren hinzu:

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
Seelenhäscher
quelle
1

Analyse auf Betriebssystemebene:

Finden Sie heraus, wo die Datenbank auf der Festplatte gespeichert ist:

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

Suchen Sie nach den neuesten Änderungen

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

Sollte auf allen Datenbanktypen funktionieren.

John McLean
quelle
0

Holen Sie sich einfach das vom Dateisystem geänderte Dateidatum. In meiner Sprache heißt das:

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

Ausgabe:

1/25/2013 06:04:10 AM
Steve Wood
quelle
6
sieht aus wie ein nicht tragbarer Hack, eine Standardmethode, die überall funktionieren würde, wäre besser
Tejesh Alimilli
0

Wenn Sie Linux ausführen, können Sie mit inotify die Tabelle oder das Datenbankverzeichnis anzeigen. inotify ist in PHP, node.js, perl verfügbar und ich vermute die meisten anderen Sprachen. Natürlich müssen Sie inotify installiert haben oder von Ihrem ISP installieren lassen. Viele ISP werden nicht.

bartonlp
quelle
2
Dateisystemprüfungen sind nicht sinnvoll, wenn Ihre Datenbank auf einem separaten Server ausgeführt wird
Sam Dufel
0

Ich bin mir nicht sicher, ob dies von Interesse wäre. Die Verwendung von mysqlproxy zwischen mysql und Clients und die Verwendung eines lua-Skripts zum Aktualisieren eines Schlüsselwerts in memcached gemäß interessanten Tabellenänderungen UPDATE, DELETE, INSERT war die Lösung, die ich vor kurzem durchgeführt habe. Wenn der Wrapper Hooks oder Trigger in PHP unterstützt, könnte dies einfacher gewesen sein. Keiner der Wrapper tut dies derzeit.

Jiju Thomas Mathew
quelle
0

Ich habe eine Spalte nach Namen erstellt: update-at in phpMyAdmin und die aktuelle Uhrzeit von der Date () -Methode in meinem Code (nodejs) erhalten. Bei jeder Änderung in der Tabelle enthält diese Spalte den Zeitpunkt der Änderungen.

saeed
quelle
1
Willkommen bei StackOverflow! Bitte bearbeiten Sie Ihre Antwort , um einen Teil des von Ihnen verwendeten Codes sowie eine Erklärung zu enthalten, warum Sie sich für diese Methode entschieden haben. Diese Frage ist fast elf Jahre alt und hat bereits eine akzeptierte, gut bewertete Antwort. Ihre Antwort wird ohne Code oder Erklärung wahrscheinlich herabgestuft oder gelöscht. Wenn Sie es so bearbeiten, dass es diese Dinge enthält, können Sie seinen Platz in diesem Beitrag rechtfertigen.
Das_Geek
0

a) Es werden alle Tabellen und die letzten Aktualisierungsdaten angezeigt

SHOW TABLE STATUS FROM db_name;

Dann können Sie weiter nach einer bestimmten Tabelle fragen:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Wie in den obigen Beispielen können Sie die Sortierung nach 'Update_time' nicht verwenden, aber mit SELECT können Sie:

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

um weiter nach einem bestimmten Tisch zu fragen:

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

Das habe ich getan, ich hoffe es hilft.

<?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'];
    }
?>
Andrés Chandía
quelle
2
Warum würdest du gerne hier verwenden?
Kyle Buser
3
@WesleyMurch: Das <font> -Tag ist veraltet.
Siride
-9

Zwischenspeichern Sie die Abfrage in einer globalen Variablen, wenn sie nicht verfügbar ist.

Erstellen Sie eine Webseite, um zu erzwingen, dass der Cache beim Aktualisieren neu geladen wird.

Fügen Sie einen Aufruf zur Seite zum erneuten Laden in Ihre Bereitstellungsskripts ein.

Kieveli
quelle
2
Sie können Variablen zwischen unabhängigen Aufrufen einer PHP-Seite nicht ohne fremde Hilfe "zwischenspeichern".
Alnitak