Як я можу дізнатися, коли таблиця MySQL востаннє оновлена?


176

У нижньому колонтитулі моєї сторінки я хотів би додати щось на кшталт "востаннє оновлено xx / xx / 200x", причому ця дата в останній раз була оновлена ​​певною таблицею mySQL.

Який найкращий спосіб зробити це? Чи є функція для отримання останньої оновленої дати? Чи повинен я отримувати доступ до бази даних кожного разу, коли мені потрібно це значення?


Відповіді:


276

У пізніших версіях MySQL ви можете використовувати information_schemaбазу даних, щоб повідомити, коли була оновлена ​​інша таблиця:

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

Це, звичайно, означає відкриття з'єднання з базою даних.


Альтернативним варіантом було б "торкнутися" певного файлу при оновленні таблиці MySQL:

Про оновлення бази даних:

  • Відкрийте файл часової позначки в O_RDRWрежимі
  • close це знову

або альтернативно

  • використання touch(), еквівалент utimes()функції PHP , для зміни часової позначки файлу.

На сторінці відображення:

  • використовувати stat()для зчитування часу модифікації файлу.

9
Докладніше про обмеження InnoDB див. Dev.mysql.com/doc/refman/5.5/uk/show-table-status.html ( show table statusвикористовує information_schema.tables)
KCD

11
Як UPDATE_TIMEметод і show table statusметод нижче доступні тільки з MyISAM двигуна, а НЕ InnoDB. Хоча це вказано як помилка , він згадується в MySQL 5.5 Reference , де також йдеться про те, що file_per_tableрежим є ненадійним показником часу модифікації.
idoimaging

5
Знову ж таки, не працює на InnoDB, оскільки mysql f ** king buggy: bugs.mysql.com/bug.php?id=14374
TMS

7
Для MySQL 5.7.2+ і він також працює для InnoDB : "Починаючи з MySQL 5.7.2, UPDATE_TIME відображає значення часової позначки для останнього UPDATE, INSERT або DELETE, виконаного на таблицях InnoDB, які не розділені. Раніше UPDATE_TIME відображало значення NULL для таблиць InnoDB. "
Петро В. Морч

2
Схоже, для мене перезапуск не зберігається (у версії 5.7.11).

58

У мене немає бази даних information_schema, використовуючи mysql версії 4.1.16, тому в цьому випадку ви можете виконати запит на це:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Він поверне ці стовпці:

| Назва | Двигун | Версія | Рядок_формат | Рядки | Avg_row_length 
| Data_length | Max_data_length | Index_length | Безкоштовно | Auto_increment
| Create_time | Update_time | Check_time | Збір
| Контрольна сума | Create_options | Коментар |

Як ви бачите, є стовпець під назвою " Update_time ", який показує вам останній час оновлення для вашого_table .


2
Він також виконує швидше (4x), ніж SELECT заяву
jmav

1
Насправді більшість таких команд SHOW просто відображаються на запити Information_schema внутрішньо, тому ця відповідь дає точно такі ж дані, як відповідь Alnitak вище. І ajacian81 є правильним - він не працює для двигуна зберігання даних за замовчуванням MySQL, InnoDB.
Білл Карвін

55

Я здивований, що ніхто не запропонував відстежувати час останнього оновлення за ряд:

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;

Це оновлює часову позначку, навіть якщо ми не згадували її в ОНОВЛЕННІ.

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

Тепер ви можете запитувати MAX ():

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

Справді, для TIMESTAMP потрібно більше пам’яті (4 байти в рядку).
Але це працює для таблиць InnoDB до 5.7.15 версії MySQL, що INFORMATION_SCHEMA.TABLES.UPDATE_TIMEне робить.


10
+1 Що стосується мене, то це єдина правильна відповідь на це питання. Питання справді хоче знати, коли оновлюються відповідні дані, а не тоді, коли таблиця (яка не має значення для користувача) може бути або не може бути змінена з будь-якої причини.
Сіріде

23
Але якщо ви видалите запис із меншим часом оновлення, MAX (updated_at) не працюватиме.
Аммамон

3
@Ammamon, правда, якщо вам також потрібно враховувати видалення, це рішення не відображає цього. Тригер для оновлення зведеної таблиці може бути єдиним комплексним рішенням, але це створить вузьке місце.
Білл Карвін

2
для більшості випадків знання видалення не буде настільки релевантним, і багато апп вищого рівня справді не видаляються з багатьох таблиць, а просто скидають прапор на еквівалент.
Самуель Фулман

1
@Pavan, різниці немає, ви просто покладаєтесь на поведінку за замовчуванням, і мій приклад чітко визначає варіант. Але параметр ідентичний поведінці за замовчуванням.
Білл Карвін

13

Найпростіше було б перевірити часову позначку файлів таблиць на диску. Наприклад, ви можете перевірити в своєму каталозі даних

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

Це повинно дати вам список усіх таблиць із таблицею, коли вона востаннє була змінена найперше, спочатку.


Дійсно чудова відповідь, оскільки UPDATE_TIME - NULL для всіх таблиць у моєму випадку (MariaDb)
Олександр Васильєв,

Файли ibd зберігають лише структуру таблиці. За замовчуванням дані зберігаються у ibdata1, тому часова мітка файлу ibd не буде оновлюватися при зміні даних у таблиці. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow

7

Для списку останніх змін таблиці використовуйте це:

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

3
Чому всі мої UPDATE_TIMEнедійсні? Будь-яка ідея?
Metafaniel

5
Ваш UPDATE_TIME недійсний, оскільки ви використовуєте InnoDB замість MyISAM. InnoDB, як правило, кращий вибір, але він не підтримує UPDATE_TIME.
Xaraxia

5

Я створив би тригер, який фіксує всі оновлення / вставки / видалення та записує часові позначки в користувацьку таблицю, щось на зразок назви таблиці | мітка часу

Просто тому, що мені не подобається ідея безпосередньо читати внутрішні системні таблиці db-сервера


1
Це здається хорошим рішенням для MS SQL, оскільки немає UPDATE_TIMEстовпця, як у MySQL.
Дарсі

3

Хоча є прийнята відповідь, я не вважаю, що вона є правильною. Це найпростіший спосіб досягти необхідного, але навіть якщо це вже ввімкнено в InnoDB (насправді документи говорять вам, що ви все одно повинні отримати NULL ...), якщо ви читаєте документи MySQL , навіть у поточній версії (8.0) за допомогою UPDATE_TIME є не правильний варіант, тому що:

Часові позначки не зберігаються при перезапуску сервера або при виведенні таблиці з кеша словника даних InnoDB.

Якщо я правильно розумію (зараз не можу перевірити це на сервері), часова марка скидається після перезавантаження сервера.

Що ж стосується реальних (і, ну, дорогих) рішень, у вас є Білл Karwin в рішенні з CURRENT_TIMESTAMP , і я хотів би запропонувати іншу, яка заснована на тригерах (я використовую це один).

Ви починаєте з створення окремої таблиці (або, можливо, у вас є інша таблиця, яка може бути використана для цієї мети), яка буде працювати як сховище для глобальних змінних (тут часові позначки). Вам потрібно зберегти два поля - ім’я таблиці (або будь-яке значення, яке ви хочете зберегти тут як ідентифікатор таблиці) та часову позначку. Після його отримання слід ініціалізувати його з цією таблицею id + дата початку (ЗАРАЗ () - хороший вибір :)).

Тепер ви переходите до таблиць, які ви хочете спостерігати, і додайте тригери ПІСЛЯ ВСТАВЛЕННЯ / ОНОВЛЕННЯ / ВИДАЛЕННЯ за допомогою цієї чи подібної процедури:

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

Аналіз рівня ОС:

Знайдіть, де БД зберігається на диску:

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

Перевірте наявність останніх змін

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

Має працювати над усіма типами баз даних.


0

Просто захопіть дату файлу, змінену з файлової системи. Моєю мовою це:

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

Вихід:

1/25/2013 06:04:10 AM

6
виглядає як високопортативний хак, краще було б стандартним способом, який би працював скрізь
Tejesh Alimilli

0

Якщо ви працюєте з Linux, ви можете використовувати inotify для перегляду таблиці або каталогу баз даних. inotify доступний на PHP, node.js, perl, і я підозрюю більшість інших мов. Звичайно, ви повинні встановити інотифікувати або встановити його провайдером. Багато провайдера не будуть.


2
Перевірка файлової системи не корисна, якщо ваша база даних працює на окремому сервері
Sam Dufel

0

Не впевнений, чи це зацікавило б. Використання mysqlproxy між mysql та клієнтами та використання скрипту lua для оновлення ключового значення в memcached відповідно до цікавих змін таблиці UPDATE, DELETE, INSERT було рішенням, яке я зробив зовсім недавно. Якщо обгортка підтримує гачки або тригери в php, це могло бути полегше. Ніхто із фасовок, що стають зараз, цього не робить.


0

Я зробив стовпчик на ім'я: update-at у phpMyAdmin і отримав поточний час із методу Date () у своєму коді (nodejs). з кожною зміною таблиці в цьому стовпці міститься час змін.


1
Ласкаво просимо до StackOverflow! Будь ласка редагувати свою відповідь , щоб включити деякі з коду , який ви використовували, а також пояснення того , чому ви вирішили зробити це таким чином. На це запитання майже одинадцять років , і він вже має прийняту, добре схвалену відповідь. Ваша відповідь, без якогось коду чи пояснення, швидше за все буде залишена або видалена. Відредагування, щоб включити ці речі, допоможе виправдати своє місце в цій публікації.
Das_Geek

0

а) Він покаже всі таблиці та дати останнього оновлення

SHOW TABLE STATUS FROM db_name;

тоді ви можете додатково запитати конкретну таблицю:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Як у наведених вище прикладах, ви не можете використовувати сортування за "Update_time", але за допомогою SELECT ви можете:

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

далі запитати про конкретну таблицю:

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

-1

Це я і зробив, сподіваюся, це допоможе.

<?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
Чому б ти використовував, як тут?
Кайл Бусер

3
@WesleyMurch: тег <font> застарілий.
siride

-9

Кешуйте запит у глобальній змінній, коли він недоступний.

Створіть веб-сторінку, щоб змусити перезавантажувати кеш-пам'ять під час оновлення.

Додайте дзвінок на сторінку для перезавантаження у сценарії розгортання.


2
ви не можете "кешувати" змінні між незалежними викликами сторінки PHP без сторонньої допомоги.
Альнітак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.