Comment savoir quand une table MySQL a été mise à jour pour la dernière fois?

176

Dans le pied de page de ma page, je voudrais ajouter quelque chose comme "dernière mise à jour le xx / xx / 200x" avec cette date étant la dernière fois qu'une certaine table mySQL a été mise à jour.

Quelle est la meilleure façon de le faire? Existe-t-il une fonction pour récupérer la dernière date de mise à jour? Dois-je accéder à la base de données chaque fois que j'ai besoin de cette valeur?

Rage
la source

Réponses:

277

Dans les versions ultérieures de MySQL, vous pouvez utiliser la information_schemabase de données pour vous dire quand une autre table a été mise à jour:

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

Cela signifie bien sûr l'ouverture d'une connexion à la base de données.


Une autre option serait de "toucher" un fichier particulier chaque fois que la table MySQL est mise à jour:

Sur les mises à jour de la base de données:

  • Ouvrez votre fichier d'horodatage en O_RDRWmode
  • close ça encore

Ou bien

  • use touch(), l'équivalent PHP de la utimes()fonction, pour modifier l'horodatage du fichier.

Affichage sur la page:

  • utilisez stat()pour relire l'heure de modification du fichier.
Alnitak
la source
9
Pour plus de détails, y compris les limitations d'InnoDB, voir dev.mysql.com/doc/refman/5.5/en/show-table-status.html ( show table statusutilise information_schema.tables)
KCD
11
La UPDATE_TIMEméthode et la show table statusméthode ci-dessous sont disponibles uniquement avec le moteur MyISAM, pas InnoDB. Bien que cela soit répertorié comme un bogue , il est mentionné dans la référence MySQL 5.5 , qui indique également que le file_per_tablemode est un indicateur peu fiable de l'heure de modification.
idoimaging
5
Encore une fois, ne fonctionne pas sur InnoDB car mysql est f ** king buggy: bugs.mysql.com/bug.php?id=14374
TMS
7
Pour MySQL 5.7.2+, cela fonctionne également pour InnoDB : "À partir de MySQL 5.7.2, UPDATE_TIME affiche une valeur d'horodatage pour le dernier UPDATE, INSERT ou DELETE effectué sur les tables InnoDB qui ne sont pas partitionnées. Auparavant, UPDATE_TIME affichait une valeur NULL pour les tables InnoDB. "
Peter V.Mørch
2
Cela ne semble pas persister au redémarrage pour moi (sur la version 5.7.11).
58

Je n'ai pas de base de données information_schema, en utilisant mysql version 4.1.16, donc dans ce cas, vous pouvez interroger ceci:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Il renverra ces colonnes:

| Nom | Moteur | Version | Row_format | Rows | Avg_row_length 
| Data_length | Max_data_length | Index_length | Data_free | Auto_increment
| Create_time | Update_time | Check_time | Collation
| Checksum | Create_options | Commentaire |

Comme vous pouvez le voir, il existe une colonne appelée: " Update_time " qui vous montre l'heure de la dernière mise à jour de votre_table .

Radu Maris
la source
2
Il fonctionne également plus rapidement (4x) que l'instruction SELECT
jmav
1
En fait, la plupart des commandes SHOW comme celle-ci sont simplement mappées aux requêtes Information_schema en interne, donc cette réponse donne exactement les mêmes données que la réponse d'Alnitak ci-dessus. Et ajacian81 est correct - cela ne fonctionne pas pour le moteur de stockage par défaut de MySQL, InnoDB.
Bill Karwin
56

Je suis surpris que personne n'ait suggéré de suivre l'heure de la dernière mise à jour par ligne:

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;

Cela met à jour l'horodatage même si nous ne l'avons pas mentionné dans la mise à jour.

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

Vous pouvez maintenant interroger le MAX ():

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

Certes, cela nécessite plus de stockage (4 octets par ligne pour TIMESTAMP).
Mais cela fonctionne pour les tables InnoDB antérieures à la version 5.7.15 de MySQL, ce qui INFORMATION_SCHEMA.TABLES.UPDATE_TIMEne fonctionne pas.

Bill Karwin
la source
10
+1 En ce qui me concerne, c'est la seule bonne réponse à cette question. La question veut vraiment savoir quand les données pertinentes sont mises à jour, et non quand une table (qui n'est pas pertinente pour l'utilisateur) peut ou non avoir été modifiée pour une raison quelconque.
siride
23
Mais si vous supprimez un enregistrement avec un temps de mise à jour inférieur, MAX (updated_at) ne fonctionnera pas.
Ammamon
3
@Ammamon, vrai, si vous devez également tenir compte des suppressions, cette solution ne le reflète pas. Un déclencheur pour mettre à jour un tableau récapitulatif peut être la seule solution complète, mais cela créerait un goulot d'étranglement.
Bill Karwin
2
pour la plupart des instances, savoir que la suppression ne serait pas aussi pertinente, et de nombreux aps de niveau supérieur ne suppriment pas vraiment de nombreuses tables, mais annulent simplement un indicateur pour l'équivalent.
Samuel Fullman
1
@Pavan, il n'y a pas de différence, vous comptez simplement sur le comportement par défaut, et mon exemple décrit l'option explicitement. Mais l'option est identique au comportement par défaut.
Bill Karwin
13

La chose la plus simple serait de vérifier l'horodatage des fichiers de table sur le disque. Par exemple, vous pouvez vérifier sous votre répertoire de données

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

Cela devrait vous donner la liste de toutes les tables avec la table lors de la dernière modification la plus ancienne, en premier.

user2654744
la source
Vraiment bonne réponse puisque UPDATE_TIME est NULL pour toutes les tables de mon cas (MariaDb)
Alexander Vasiljev
Les fichiers ibd ne stockent que la structure de la table. Par défaut, les données sont stockées dans ibdata1 afin que l'horodatage du fichier ibd ne soit pas mis à jour lorsque les données sont modifiées dans la table. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow
@StackUnderflow, ce que vous avez dit n'est pas exact. Les fichiers ibd stockent des données et des index pour un tablespace, qui contient une ou plusieurs tables. Si les données sont stockées dans ibdata1, il n'y aura pas de fichier ibd. Le stockage des données dans un fichier par table est la méthode par défaut depuis MySQL 5.6 en 2013.
Bill Karwin
7

Pour une liste des modifications récentes de la table, utilisez ceci:

SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME
François Bourgeois
la source
3
Pourquoi tous mes UPDATE_TIMEsont nuls? Une idée?
Metafaniel
5
Votre UPDATE_TIME est nul, car vous utilisez InnoDB au lieu de MyISAM. InnoDB est généralement le meilleur choix, mais il ne prend pas en charge UPDATE_TIME.
Xaraxia
5

Je créerais un déclencheur qui attrape toutes les mises à jour / inserts / suppressions et j'écrirais l'horodatage dans une table personnalisée, quelque chose comme tablename | horodatage

Juste parce que je n'aime pas l'idée de lire directement les tables système internes du serveur db

Mikhail
la source
1
Cela semble être une bonne solution pour MS SQL, car il n'y a pas de UPDATE_TIMEcolonne comme dans MySQL.
Darcy
3

Bien qu'il y ait une réponse acceptée, je ne pense pas que ce soit la bonne. C'est le moyen le plus simple de réaliser ce qui est nécessaire, mais même s'il est déjà activé dans InnoDB (en fait, les documents vous disent que vous devriez toujours obtenir NULL ...), si vous lisez des documents MySQL , même dans la version actuelle (8.0) en utilisant UPDATE_TIME est pas la bonne option, car:

Les horodatages ne sont pas conservés lorsque le serveur est redémarré ou lorsque la table est expulsée du cache du dictionnaire de données InnoDB.

Si je comprends bien (je ne peux pas le vérifier sur un serveur pour le moment), l'horodatage est réinitialisé après le redémarrage du serveur.

En ce qui concerne les solutions réelles (et, enfin, coûteuses), vous avez la solution de Bill Karwin avec CURRENT_TIMESTAMP et j'aimerais en proposer une différente, basée sur des déclencheurs (j'utilise celui-là).

Vous commencez par créer une table séparée (ou peut-être avez-vous une autre table qui peut être utilisée à cet effet) qui fonctionnera comme un stockage pour les variables globales (ici les horodatages). Vous devez stocker deux champs: le nom de la table (ou la valeur que vous souhaitez conserver ici en tant qu'ID de table) et l'horodatage. Une fois que vous l'avez, vous devez l'initialiser avec cet identifiant de table + date de début (NOW () est un bon choix :)).

Maintenant, vous passez aux tables que vous souhaitez observer et ajoutez des déclencheurs APRÈS INSERT / UPDATE / DELETE avec cette procédure ou une procédure similaire:

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
Soul Reaver
la source
1

Analyse au niveau du système d'exploitation:

Trouvez où la base de données est stockée sur le disque:

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

Rechercher les modifications les plus récentes

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

Devrait fonctionner sur tous les types de bases de données.

John McLean
la source
0

Saisissez simplement la date du fichier modifiée à partir du système de fichiers. Dans ma langue c'est:

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

Production:

1/25/2013 06:04:10 AM
Steve Wood
la source
6
ressemble à un hack hautement non portable, une méthode standard qui fonctionnerait partout serait meilleure
Tejesh Alimilli
0

Si vous utilisez Linux, vous pouvez utiliser inotify pour consulter la table ou le répertoire de la base de données. inotify est disponible sur PHP, node.js, perl et je soupçonne la plupart des autres langages. Bien sûr, vous devez avoir installé inotify ou l'avoir fait installer par votre FAI. Beaucoup de FAI ne le feront pas.

Bartonlp
la source
2
Les vérifications du système de fichiers ne sont pas utiles si votre base de données s'exécute sur un serveur séparé
Sam Dufel
0

Je ne sais pas si cela présente un quelconque intérêt. Utiliser mysqlproxy entre mysql et les clients, et utiliser un script lua pour mettre à jour une valeur clé dans memcached en fonction des changements de table intéressants UPDATE, DELETE, INSERT était la solution que j'ai faite assez récemment. Si le wrapper supportait des hooks ou des déclencheurs en php, cela aurait pu être eaiser. Aucun des wrappers ne le fait pour le moment.

Jiju Thomas Mathew
la source
0

J'ai créé une colonne par nom: update-at dans phpMyAdmin et j'ai obtenu l'heure actuelle de la méthode Date () dans mon code (nodejs). à chaque changement dans le tableau, cette colonne contient l'heure des changements.

saeed
la source
1
Bienvenue dans StackOverflow! Veuillez modifier votre réponse pour inclure une partie du code que vous avez utilisé, ainsi qu'une explication des raisons pour lesquelles vous avez choisi de le faire de cette façon. Cette question a presque onze ans et a déjà une réponse acceptée et bien votée. Votre réponse, sans code ni explication, sera probablement rejetée ou supprimée. Le modifier pour inclure ces éléments aidera à justifier sa place sur ce message.
Das_Geek
0

a) Il vous montrera toutes les tables et les dernières dates de mise à jour

SHOW TABLE STATUS FROM db_name;

ensuite, vous pouvez en outre demander une table spécifique:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Comme dans les exemples ci-dessus, vous ne pouvez pas utiliser le tri sur 'Update_time' mais en utilisant SELECT, vous pouvez:

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

pour en savoir plus sur une table particulière:

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

C'est ce que j'ai fait, j'espère que cela aide.

<?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
la source
2
Pourquoi utiliseriez-vous comme ici?
Kyle Buser
3
@WesleyMurch: la balise <font> est bien obsolète.
siride
-9

Mettez la requête en cache dans une variable globale lorsqu'elle n'est pas disponible.

Créez une page Web pour forcer le rechargement du cache lorsque vous le mettez à jour.

Ajoutez un appel à la page de rechargement dans vos scripts de déploiement.

Kieveli
la source
2
vous ne pouvez pas "mettre en cache" des variables entre des invocations indépendantes d'une page PHP sans assistance extérieure.
Alnitak