Jak mogę sprawdzić, kiedy tabela MySQL została ostatnio zaktualizowana?


176

W stopce mojej strony chciałbym dodać coś w stylu „ostatnia aktualizacja xx / xx / 200x”, z datą ostatniej aktualizacji danej tabeli MySQL.

Jaki jest najlepszy sposób, aby to zrobić? Czy istnieje funkcja pobierania ostatniej zaktualizowanej daty? Czy powinienem mieć dostęp do bazy danych za każdym razem, gdy potrzebuję tej wartości?


Odpowiedzi:


276

W późniejszych wersjach MySQL możesz użyć information_schemabazy danych, aby poinformować Cię, kiedy została zaktualizowana inna tabela:

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

Oznacza to oczywiście otwarcie połączenia z bazą danych.


Alternatywną opcją byłoby „dotknięcie” określonego pliku przy każdej aktualizacji tabeli MySQL:

W przypadku aktualizacji bazy danych:

  • Otwórz plik z sygnaturą czasową w O_RDRWtrybie
  • close to znowu

lub alternatywnie

  • użyj touch(), odpowiednika utimes()funkcji PHP , do zmiany znacznika czasu pliku.

Wyświetlanie na stronie:

  • użyj, stat()aby odczytać czas modyfikacji pliku.

9
Aby uzyskać szczegółowe informacje, w tym ograniczenia InnoDB, patrz dev.mysql.com/doc/refman/5.5/en/show-table-status.html ( show table statuszastosowania information_schema.tables)
KCD

11
Zarówno UPDATE_TIMEmetoda, a show table statusponiżej metody są dostępne tylko przy silniku MyISAM, InnoDB nie. Chociaż jest to wymienione jako błąd , jest to wspomniane w dokumencie MySQL 5.5 Reference , który mówi również, że file_per_tabletryb jest niewiarygodnym wskaźnikiem czasu modyfikacji.
idoimaging

5
Ponownie, nie działa na InnoDB, ponieważ mysql jest pieprzonym błędem
TMS

7
W przypadku MySQL 5.7.2+ działa również dla InnoDB : „Począwszy od MySQL 5.7.2, UPDATE_TIME wyświetla wartość sygnatury czasowej dla ostatniego UPDATE, INSERT lub DELETE wykonanego na tabelach InnoDB, które nie są podzielone na partycje. Wcześniej UPDATE_TIME wyświetlało wartość NULL dla tabel InnoDB ”.
Peter V. Mørch

2
Wydaje się, że to nie utrzymuje się przy ponownym uruchomieniu (w wersji 5.7.11).

58

Nie mam bazy danych information_schema, używam mysql w wersji 4.1.16, więc w tym przypadku możesz zapytać o to:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Zwróci te kolumny:

| Imię | Silnik | Wersja | Row_format | Wiersze | Avg_row_length 
| Długość_danych | Max_data_length | Długość_indeksu | Brak danych | Auto_increment
| Czas_tworzenia | Update_time | Check_time | Sortowanie
| Suma kontrolna | Create_options | Komentarz |

Jak widać, istnieje kolumna o nazwie: „ Czas_aktualizacji ”, która pokazuje czas ostatniej aktualizacji dla Twojej_tabeli .


2
Działa również szybciej (4x) niż instrukcja SELECT
jmav

1
W rzeczywistości większość poleceń SHOW takich jak ta jest po prostu odwzorowywana wewnętrznie na zapytania Information_schema, więc ta odpowiedź daje dokładnie te same dane, co powyższa odpowiedź od Alnitaka. Ajacian81 jest poprawny - nie działa z domyślnym silnikiem pamięci MySQL, InnoDB.
Bill Karwin,

55

Jestem zaskoczony, że nikt nie zasugerował śledzenia czasu ostatniej aktualizacji w każdym wierszu:

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;

To aktualizuje sygnaturę czasową, mimo że nie wspomnieliśmy o tym w AKTUALIZACJI.

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

Teraz możesz zapytać o MAX ():

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

Trzeba przyznać, że wymaga to więcej miejsca (4 bajty na wiersz dla TIMESTAMP).
Ale to działa dla tabel InnoDB przed wersją MySQL 5.7.15, co INFORMATION_SCHEMA.TABLES.UPDATE_TIMEnie działa.


10
+1 Jeśli o mnie chodzi, to jedyna prawidłowa odpowiedź na to pytanie. Pytanie naprawdę chce wiedzieć, kiedy aktualizowane są odpowiednie dane, a nie kiedy tabela (która jest nieistotna dla użytkownika) mogła lub nie została zmieniona z jakiegokolwiek powodu.
siride

23
Ale jeśli usuniesz rekord z krótszym czasem aktualizacji, MAX (updated_at) nie będzie działać.
Ammamon

3
@Ammamon, prawda, jeśli musisz również uwzględnić usunięcia, to rozwiązanie tego nie odzwierciedla. Wyzwalacz aktualizacji tabeli podsumowań może być jedynym kompleksowym rozwiązaniem, ale spowodowałoby to wąskie gardło.
Bill Karwin,

2
w większości przypadków wiedza o usunięciu nie byłaby tak istotna, a wiele apli wyższego poziomu tak naprawdę nie usuwa z wielu tabel, ale po prostu usuwa flagę dla odpowiednika.
Samuel Fullman

1
@Pavan, nie ma różnicy, polegasz tylko na domyślnym zachowaniu, a mój przykład wyraźnie określa tę opcję. Ale ta opcja jest identyczna z domyślnym zachowaniem.
Bill Karwin

13

Najprościej byłoby sprawdzić sygnaturę czasową plików tabel na dysku. Na przykład możesz sprawdzić w swoim katalogu danych

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

Powinno to dać ci listę wszystkich tabel z tabelą, kiedy była ostatnio modyfikowana, jako pierwsza.


Naprawdę świetna odpowiedź, ponieważ UPDATE_TIME ma wartość NULL dla wszystkich tabel w moim przypadku (MariaDb)
Alexander Vasiljev

Pliki ibd przechowują tylko strukturę tabeli. Domyślnie dane są przechowywane w ibdata1, więc sygnatura czasowa pliku ibd nie będzie aktualizowana po zmianie danych w tabeli. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow

7

Aby zobaczyć listę ostatnich zmian tabeli, użyj tego:

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

3
Dlaczego wszystkie moje UPDATE_TIMEsą zerowe? Dowolny pomysł?
Metafaniel

5
Twój UPDATE_TIME jest pusty, ponieważ używasz InnoDB zamiast MyISAM. InnoDB jest ogólnie lepszym wyborem, ale nie obsługuje UPDATE_TIME.
Xaraxia

5

Utworzyłbym wyzwalacz, który przechwytuje wszystkie aktualizacje / wstawienia / usunięcia i zapisuje znacznik czasu w niestandardowej tabeli, coś w rodzaju nazwy tabeli | znak czasu

Tylko dlatego, że nie podoba mi się pomysł bezpośredniego odczytywania wewnętrznych tabel systemowych serwera db


1
Wydaje się, że jest to dobre rozwiązanie dla MS SQL, ponieważ nie ma takiej UPDATE_TIMEkolumny jak w MySQL.
Darcy,

3

Chociaż istnieje akceptowana odpowiedź, nie uważam, że jest ona właściwa. Jest to najprostszy sposób na osiągnięcie tego, co jest potrzebne, ale nawet jeśli jest już włączony w InnoDB (w rzeczywistości dokumenty mówią, że nadal powinieneś uzyskać NULL ...), jeśli czytasz dokumenty MySQL , nawet w aktualnej wersji (8.0) używając UPDATE_TIME jest niewłaściwa opcja, ponieważ:

Sygnatury czasowe nie są utrwalane po ponownym uruchomieniu serwera lub po usunięciu tabeli z pamięci podręcznej słownika danych InnoDB.

Jeśli dobrze rozumiem (nie mogę tego teraz zweryfikować na serwerze), znacznik czasu zostanie zresetowany po ponownym uruchomieniu serwera.

Jak dla prawdziwych (i dobrze, kosztownych) rozwiązań, masz Bill Karwin za rozwiązanie z CURRENT_TIMESTAMP i chciałbym zaproponować inny, który jest oparty na wyzwalaczy (używam tego jednego).

Zaczynasz od stworzenia oddzielnej tabeli (a może masz jakąś inną tabelę, która może być użyta do tego celu), która będzie działać jak magazyn dla zmiennych globalnych (tutaj znaczniki czasu). Musisz przechowywać dwa pola - nazwę tabeli (lub jakąkolwiek wartość, którą chcesz tutaj zachować jako identyfikator tabeli) i znacznik czasu. Gdy już to zrobisz, powinieneś zainicjować go z tym id tabeli + data początkowa (NOW () to dobry wybór :)).

Teraz przechodzisz do tabel, które chcesz obserwować, i dodajesz wyzwalacze PO WSTAWIENIU / AKTUALIZACJI / USUNIĘCIU za pomocą tej lub podobnej procedury:

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

Analiza poziomu systemu operacyjnego:

Znajdź miejsce przechowywania bazy danych na dysku:

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

Sprawdź najnowsze modyfikacje

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

Powinien działać na wszystkich typach baz danych.


0

Po prostu pobierz datę pliku zmodyfikowaną z systemu plików. W moim języku to znaczy:

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

Wynik:

1/25/2013 06:04:10 AM

6
wygląda na wysoce nieprzenośny hack, standardowy sposób, który działałby wszędzie, byłby lepszy
Tejesh Alimilli

0

Jeśli używasz Linuksa, możesz użyć inotify do przejrzenia tabeli lub katalogu bazy danych. inotify jest dostępny z PHP, node.js, perl i podejrzewam, że większość innych języków. Oczywiście musisz mieć zainstalowany inotify lub mieć go zainstalowanego przez dostawcę usług internetowych. Wielu dostawców usług internetowych tego nie zrobi.


2
Sprawdzanie systemu plików nie jest przydatne, jeśli baza danych działa na osobnym serwerze
Sam Dufel

0

Nie jestem pewien, czy to mogłoby być interesujące. Użycie mysqlproxy pomiędzy mysql a klientami oraz użycie skryptu lua do aktualizacji wartości klucza w memcached zgodnie z interesującymi zmianami tabeli UPDATE, DELETE, INSERT było rozwiązaniem, które zrobiłem całkiem niedawno. Gdyby opakowanie wspierało przechwyty lub wyzwalacze w php, mogłoby to być łatwiejsze. Żaden z opakowań na razie tego nie robi.


0

Zrobiłem kolumnę według nazwy: update-at w phpMyAdmin i uzyskałem aktualny czas z metody Date () w moim kodzie (nodejs). z każdą zmianą w tabeli ta kolumna zawiera czas zmian.


1
Witamy w StackOverflow! Proszę edytować odpowiedź na to niektóre z kodem używanym, a także wyjaśnienie , dlaczego zdecydowałeś się zrobić to w ten sposób. To pytanie ma prawie jedenaście lat i ma już zaakceptowaną, dobrze przyjętą odpowiedź. Twoja odpowiedź, bez kodu lub wyjaśnienia, zostanie prawdopodobnie odrzucona lub usunięta. Edycja go tak, aby zawierała te rzeczy, pomoże uzasadnić jego miejsce w tym poście.
Das_Geek

0

a) Pokaże wszystkie tabele i tam ostatnie daty aktualizacji

SHOW TABLE STATUS FROM db_name;

następnie możesz zapytać o konkretną tabelę:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Jak w powyższych przykładach, nie możesz użyć sortowania według 'Update_time', ale używając SELECT możesz:

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

aby zapytać o konkretny stół:

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

-1

To właśnie zrobiłem, mam nadzieję, że to pomoże.

<?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
Dlaczego miałbyś używać tutaj?
Kyle Buser

3
@WesleyMurch: tag <font> jest przestarzały.
siride

-9

Buforuj zapytanie w zmiennej globalnej, gdy nie jest dostępna.

Utwórz stronę internetową, aby wymusić ponowne załadowanie pamięci podręcznej podczas jej aktualizacji.

Dodaj wywołanie do strony ponownego ładowania w skryptach wdrażania.


2
nie możesz "buforować" zmiennych pomiędzy niezależnymi wywołaniami strony PHP bez pomocy z zewnątrz.
Alnitak
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.