¿Cómo puedo saber cuándo se actualizó por última vez una tabla MySQL?

176

En el pie de página de mi página, me gustaría agregar algo como "última actualización de xx / xx / 200x", siendo esta fecha la última vez que se ha actualizado una determinada tabla mySQL.

¿Cuál es la mejor manera de hacer eso? ¿Hay una función para recuperar la última fecha actualizada? ¿Debo acceder a la base de datos cada vez que necesito este valor?

Rabia
fuente

Respuestas:

276

En versiones posteriores de MySQL, puede usar la information_schemabase de datos para informarle cuándo se actualizó otra tabla:

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

Por supuesto, esto significa abrir una conexión a la base de datos.


Una opción alternativa sería "tocar" un archivo en particular cada vez que se actualiza la tabla MySQL:

En actualizaciones de bases de datos:

  • Abra su archivo de marca de tiempo en O_RDRWmodo
  • close de nuevo

o alternativamente

  • use touch(), el equivalente PHP de la utimes()función, para cambiar la marca de tiempo del archivo.

En la página de visualización:

  • use stat()para volver a leer el tiempo de modificación del archivo.
Alnitak
fuente
9
Para obtener detalles, incluidas las limitaciones de InnoDB, consulte dev.mysql.com/doc/refman/5.5/en/show-table-status.html ( show table statususos information_schema.tables)
KCD
11
Tanto el UPDATE_TIMEmétodo como el show table statusmétodo a continuación están disponibles solo con el motor MyISAM, no con InnoDB. Aunque esto aparece como un error , se menciona en la Referencia de MySQL 5.5 , que también dice que el file_per_tablemodo es un indicador poco confiable del tiempo de modificación.
idoimaging
55
De nuevo, no funciona en InnoDB porque mysql es un buggy f ** king: bugs.mysql.com/bug.php?id=14374
TMS
77
Para MySQL 5.7.2+ también funciona para InnoDB : "Comenzando con MySQL 5.7.2, UPDATE_TIME muestra un valor de marca de tiempo para la última UPDATE, INSERT o DELETE realizada en las tablas de InnoDB que no están particionadas. Anteriormente, UPDATE_TIME mostraba un valor NULL para tablas InnoDB ".
Peter V. Mørch
2
Esto no parece persistir en el reinicio para mí (en la versión 5.7.11).
58

No tengo la base de datos information_schema, usando mysql versión 4.1.16, por lo que en este caso puede consultar esto:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Devolverá estas columnas:

El | Nombre | Motor | Version | Row_format | Filas | Avg_row_length 
| Longitud de datos | Max_data_length | Longitud_de_ índice | Libre de datos | Aumento automático
| Create_time | Update_time | Check_time | Cotejo
| Suma de comprobación | Crear_opciones | Comentario |

Como puede ver, hay una columna llamada: " Update_time " que le muestra la última hora de actualización para your_table .

Radu Maris
fuente
2
También funciona más rápido (4x) que la instrucción SELECT
jmav
1
De hecho, la mayoría de los comandos SHOW como este simplemente se asignan a consultas de Information_schema internamente, por lo que esta respuesta proporciona exactamente los mismos datos que la respuesta de Alnitak anterior. Y ajacian81 es correcto: no funciona para el motor de almacenamiento predeterminado de MySQL, InnoDB.
Bill Karwin
55

Me sorprende que nadie haya sugerido el seguimiento del último tiempo de actualización por fila:

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;

Esto actualiza la marca de tiempo a pesar de que no lo mencionamos en la ACTUALIZACIÓN.

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

Ahora puede consultar el MAX ():

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

Es cierto que esto requiere más almacenamiento (4 bytes por fila para TIMESTAMP).
Pero esto funciona para las tablas InnoDB anteriores a la versión 5.7.15 de MySQL, que INFORMATION_SCHEMA.TABLES.UPDATE_TIMEno funciona.

Bill Karwin
fuente
10
+1 En lo que a mí respecta, esta es la única respuesta correcta a esta pregunta. La pregunta realmente quiere saber cuándo se actualizan los datos relevantes y no cuándo una tabla (que es irrelevante para el usuario) puede o no haber cambiado por cualquier razón.
siride
23
Pero si elimina un registro con un tiempo de actualización menor, MAX (updated_at) no funcionará.
Ammamon
3
@Ammamon, es cierto, si también necesita tener en cuenta las eliminaciones, esta solución no refleja eso. Un disparador para actualizar una tabla de resumen puede ser la única solución integral, pero eso crearía un cuello de botella.
Bill Karwin
2
para la mayoría de los casos, saber que la eliminación no sería tan relevante, y muchas aplicaciones de nivel superior no eliminan realmente de muchas tablas, sino que simplemente desactivan una marca para el equivalente.
Samuel Fullman
1
@Pavan, no hay diferencia, solo estás confiando en el comportamiento predeterminado, y mi ejemplo explica explícitamente la opción. Pero la opción es idéntica al comportamiento predeterminado.
Bill Karwin
13

Lo más simple sería verificar la marca de tiempo de los archivos de la tabla en el disco. Por ejemplo, puede verificar en su directorio de datos

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

Esto debería darle la lista de todas las tablas con la tabla cuando se modificó por última vez la primera vez, la primera.

usuario2654744
fuente
Muy buena respuesta ya que UPDATE_TIME es NULL para todas las tablas en mi caso (MariaDb)
Alexander Vasiljev
Los archivos ibd solo almacenan la estructura de la tabla. De forma predeterminada, los datos se almacenan en ibdata1, por lo que la marca de tiempo del archivo ibd no se actualizará cuando se modifiquen los datos en la tabla. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow
7

Para obtener una lista de los cambios recientes en la tabla, use esto:

SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME
Francois Bourgeois
fuente
3
¿Por qué todos mis UPDATE_TIMEson nulos? ¿Alguna idea?
Metafaniel
55
Su UPDATE_TIME es nulo porque está usando InnoDB en lugar de MyISAM. InnoDB es generalmente la mejor opción, pero no admite UPDATE_TIME.
Xaraxia
5

Crearía un desencadenador que capture todas las actualizaciones / inserciones / eliminaciones y escriba una marca de tiempo en una tabla personalizada, algo así como nombre de tabla | marca de tiempo

Solo porque no me gusta la idea de leer las tablas internas del sistema del servidor db directamente

Mikhail
fuente
1
Esto parece una buena solución para MS SQL, porque no hay una UPDATE_TIMEcolumna como en MySQL.
Darcy
3

Aunque hay una respuesta aceptada, no creo que sea la correcta. Es la forma más simple de lograr lo que se necesita, pero incluso si ya está habilitado en InnoDB (en realidad, los documentos le dicen que aún debe obtener NULL ...), si lee documentos de MySQL , incluso en la versión actual (8.0) usando UPDATE_TIME es no es la opción correcta porque:

Las marcas de tiempo no se conservan cuando se reinicia el servidor o cuando se desaloja la tabla de la caché del diccionario de datos InnoDB.

Si entiendo correctamente (no puedo verificarlo en un servidor en este momento), la marca de tiempo se restablece después de reiniciar el servidor.

En cuanto a las soluciones reales (y, bueno, costosas), tiene la solución de Bill Karwin con CURRENT_TIMESTAMP y me gustaría proponer una diferente, que se base en desencadenantes (estoy usando esa).

Comienza creando una tabla separada (o tal vez tenga alguna otra tabla que se pueda usar para este propósito) que funcionará como un almacenamiento para variables globales (aquí las marcas de tiempo). Debe almacenar dos campos: nombre de la tabla (o cualquier valor que desee mantener aquí como id de la tabla) y marca de tiempo. Después de tenerlo, debe inicializarlo con este id de tabla + fecha de inicio (NOW () es una buena opción :)).

Ahora, pasa a las tablas que deseas observar y agrega disparadores DESPUÉS DE INSERTAR / ACTUALIZAR / BORRAR con este procedimiento u otro similar:

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
Segador de almas
fuente
1

Análisis a nivel del sistema operativo:

Encuentre dónde está almacenada la base de datos en el disco:

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

Verifique las modificaciones más recientes

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

Debería funcionar en todos los tipos de bases de datos.

John McLean
fuente
0

Simplemente tome la fecha del archivo modificado del sistema de archivos. En mi idioma que es:

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

Salida:

1/25/2013 06:04:10 AM
Steve Wood
fuente
66
parece un hack altamente no portátil, una forma estándar que funcionaría en todas partes sería mejor
Tejesh Alimilli
0

Si está ejecutando Linux, puede usar inotify para mirar la tabla o el directorio de la base de datos. inotify está disponible en PHP, node.js, perl y sospecho que la mayoría de los otros lenguajes. Por supuesto, debe haber instalado inotify o que su ISP lo haya instalado. Muchos ISP no lo harán.

bartonlp
fuente
2
Las comprobaciones del sistema de archivos no son útiles si su base de datos se ejecuta en un servidor separado
Sam Dufel
0

No estoy seguro si esto sería de algún interés. El uso de mysqlproxy entre mysql y los clientes, y el uso de un script lua para actualizar un valor clave en memcached de acuerdo con interesantes cambios en la tabla ACTUALIZAR, ELIMINAR, INSERTAR fue la solución que hice bastante recientemente. Si el contenedor admite ganchos o disparadores en php, esto podría haber sido más fácil. Ninguno de los envoltorios a partir de ahora hace esto.

Jiju Thomas Mathew
fuente
0

Hice una columna por nombre: update-at en phpMyAdmin y obtuve la hora actual del método Date () en mi código (nodejs). Con cada cambio en la tabla, esta columna contiene el tiempo de los cambios.

Saeed
fuente
1
¡Bienvenido a StackOverflow! Por favor, editar su respuesta para incluir una parte del código que utilizó, así como una explicación de por qué ha elegido hacerlo de esta manera. Esta pregunta tiene casi once años y ya tiene una respuesta aceptada y bien votada. Su respuesta, sin algún código o explicación, probablemente será rechazada o eliminada. Editarlo para incluir esas cosas ayudará a justificar su lugar en esta publicación.
Das_Geek
0

a) Te mostrará todas las tablas y las últimas fechas de actualización

SHOW TABLE STATUS FROM db_name;

luego, puede solicitar una tabla específica:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Como en los ejemplos anteriores, no puede usar la ordenación en 'Update_time' pero con SELECT puede:

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

para preguntar más sobre una tabla en particular:

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

Esto es lo que hice, espero que ayude.

<?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
fuente
2
¿Por qué usarías como aquí?
Kyle Buser
3
@WesleyMurch: la etiqueta <font> está en desuso.
siride
-9

Caché la consulta en una variable global cuando no está disponible.

Cree una página web para forzar la recarga de la memoria caché cuando la actualice.

Agregue una llamada a la página de recarga en sus scripts de implementación.

Kieveli
fuente
2
no puede "almacenar en caché" variables entre invocaciones independientes de una página PHP sin ayuda externa.
Alnitak