В нижнем колонтитуле моей страницы я хотел бы добавить что-то вроде «последнее обновление xx / xx / 200x» с этой датой, когда в последний раз обновлялась определенная таблица mySQL.
Как лучше всего это сделать? Есть ли функция для получения даты последнего обновления? Должен ли я обращаться к базе данных каждый раз, когда мне нужно это значение?






Кэшируйте запрос в глобальной переменной, если она недоступна.
Создайте веб-страницу, чтобы принудительно перезагружать кеш при его обновлении.
Добавьте вызов на страницу перезагрузки в свои сценарии развертывания.
вы не можете «кэшировать» переменные между независимыми вызовами страницы PHP без посторонней помощи.
В более поздних версиях MySQL вы можете использовать базу данных information_schema, чтобы сообщить вам, когда была обновлена другая таблица:
SELECT UPDATE_TIME
FROM information_schema.tables
WHERE TABLE_SCHEMA = 'dbname'
AND TABLE_NAME = 'tabname'
Это, конечно, означает открытие соединения с базой данных.
Альтернативный вариант - «прикоснуться» к конкретному файлу при каждом обновлении таблицы MySQL:
При обновлении базы данных:
O_RDRW.close это сноваили альтернативно
На отображении страницы:
stat() для считывания времени модификации файла.я могу манипулировать этим. означает, что если я хочу изменить значение, которое MySQL дает мне, когда я запускаю этот запрос
Для получения дополнительной информации, включая ограничения InnoDB, см. dev.mysql.com/doc/refman/5.5/en/show-table-status.html (show table status использует information_schema.tables)
Связан ли здесь UPDATE_TIME со временем изменений в информационной схеме, например. только структурные изменения ?? Разве при этом не учитываются изменения, если новые строки вставляются / обновляются / удаляются ??
Оба метода UPDATE_TIME и show table status ниже доступны только с движком MyISAM, но не InnoDB. Хотя он указан как ошибка, он упоминается в Справочник по MySQL 5.5, где также говорится, что режим file_per_table является ненадежным индикатором времени модификации.
Опять же, не работает на InnoDB, потому что mysql чертовски глючит: bugs.mysql.com/bug.php?id=14374
Для MySQL 5.7.2+ это также работает для InnoDB: «Начиная с MySQL 5.7.2, UPDATE_TIME отображает значение отметки времени для последнего UPDATE, INSERT или DELETE, выполненного для таблиц InnoDB, которые не секционированы. Ранее UPDATE_TIME отображал значение NULL для InnoDB столы ".
Кажется, это не сохраняется при перезапуске для меня (в версии 5.7.11).
Пока что у меня все работает нормально. Моя единственная проблема в том, что время обновления сбрасывается на ноль каждый день. Есть идеи?
Есть ли способ получить информацию для таблиц InnoDB в 2018 году?
@rain_ InnoDB исправляет столбец update_time в MySQL 5.7.2, но не сохраняется при перезапусках сервера (см. bugs.mysql.com/bug.php?id=14374)
Есть ли способ узнать время последнего обновления определенного поля в таблице?
У меня нет базы данных information_schema, использующей mysql версии 4.1.16, поэтому в этом случае вы можете запросить это:
SHOW TABLE STATUS FROM your_database LIKE 'your_table';
Он вернет эти столбцы:
| Name | Engine | 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 | Comment |
Как видите, есть столбец под названием «Время обновления», который показывает время последнего обновления для your_table.
Он также работает быстрее (в 4 раза), чем оператор SELECT
Фактически, большинство таких команд SHOW просто внутренне сопоставляются с запросами Information_schema, поэтому этот ответ дает точно такие же данные, что и ответ от Alnitak выше. И ajacian81 верен - он не работает для механизма хранения по умолчанию MySQL, InnoDB.
Я так и сделал, надеюсь, это поможет.
<?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'];
}
?>
Зачем вам использовать подобное здесь?
@WesleyMurch: тег <font> устарел.
Я бы создал триггер, который улавливает все обновления / вставки / удаления и записывает временную метку в настраиваемую таблицу, что-то вроде tablename | отметка времени
Просто потому, что мне не нравится идея читать внутренние системные таблицы сервера db напрямую
Это кажется хорошим решением для MS SQL, потому что здесь нет столбца UPDATE_TIME, как в MySQL.
Для списка последних изменений таблицы используйте это:
SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME
Почему все мои UPDATE_TIME нулевые? Любая идея?
Ваш UPDATE_TIME равен нулю, потому что вы используете InnoDB вместо MyISAM. InnoDB, как правило, лучший выбор, но он не поддерживает UPDATE_TIME.
Просто возьмите дату изменения файла из файловой системы. На моем языке это:
tbl_updated = file.update_time(
"C:\ProgramData\MySQL\MySQL Server 5.5\data\mydb\person.frm")
Выход:
1/25/2013 06:04:10 AM
выглядит очень непереносимым хаком, стандартный способ, который работал бы везде, был бы лучше
Если вы используете Linux, вы можете использовать inotify для просмотра таблицы или каталога базы данных. inotify доступен на PHP, node.js, perl и, как я подозреваю, на большинстве других языков. Конечно, у вас должен быть установлен inotify или ваш интернет-провайдер установил его. Много ISP не будет.
Проверки файловой системы бесполезны, если ваша база данных работает на отдельном сервере.
Я удивлен, что никто не предложил отслеживать время последнего обновления для каждой строки:
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;
Это обновляет метку времени, хотя мы не упоминали об этом в UPDATE.
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 |
+---------------------+
По общему признанию, для этого требуется больше памяти (4 байта на строку для TIMESTAMP) .
Но это работает для таблиц InnoDB до версии MySQL 5.7.15, чего нет у INFORMATION_SCHEMA.TABLES.UPDATE_TIME.
+1 Насколько я понимаю, это единственно правильный ответ на этот вопрос. Вопрос действительно хочет знать, когда обновляются соответствующие данные, а не когда таблица (которая не имеет отношения к пользователю) может или не могла быть изменена по какой-либо причине.
Но если вы удалите запись с меньшим временем обновления, MAX (updated_at) работать не будет.
@Ammamon, правда, если вам также нужно учитывать удаления, это решение не отражает этого. Триггер для обновления сводной таблицы может быть единственным комплексным решением, но это создаст узкое место.
да. Я думаю, что мы также можем обновить постоянную глобальную переменную состояния с помощью new DateTime () всякий раз, когда наша таблица вставляется, обновляется или удаляется. Отображая эту глобальную переменную состояния внизу страницы, вы можете избежать повторных проверок таблицы.
Я упоминаю об отображении нижнего колонтитула, потому что это то, что нужно спрашивающему.
для большинства случаев, когда известно, что удаление не будет иметь такого значения, и многие приложения более высокого уровня не удаляют на самом деле из многих таблиц, а просто снимают флаг для эквивалента.
Для удобства вот заявление об обновлении ALTER TABLE 'foo' ADD 'updated_at' TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE 'foo' ADD INDEX ('updated_at');
Привет, @BillKarwin В чем разница между вашим оператором обновления и этим оператором обновления: ALTER TABLE my_table ADD ModifiedTime TIMESTAMP;, взятый из этой статьи: marcus-povey.co.uk/2013/03/11/…
@Pavan, «По умолчанию в столбце первый TIMESTAMP есть как DEFAULT CURRENT_TIMESTAMP, так и ON UPDATE CURRENT_TIMESTAMP, если ни один из них не указан явно». dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.htm l
@BillKarwin не понимает разницы? Мой кажется проще реализовать, и он все равно будет обновлять метку времени при обновлении
@Pavan, нет никакой разницы, вы просто полагаетесь на поведение по умолчанию, и в моем примере опция явно прописана. Но этот параметр идентичен поведению по умолчанию.
@BillKarwin после MySQL версии 5.7.15, innoDB теперь работает с полем UPDATE_TIME в таблице information_schema.tables.
@Meloman, спасибо за подсказку, я это пропустил. Я нашел примечания к выпуску, на самом деле это было в 5.7.2. См. dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-2.html и bugs.mysql.com/bug.php?id=14374.
SELECT MAX ... может работать медленно с большими таблицами. Таблице с 2,8 миллионами требуется 2,5 секунды для определения MAX (...).
@Peter, Нет, InnoDB прочитает индекс на updated_at, чтобы получить максимальное значение. Не нужно вообще читать таблицу, и не имеет значения, насколько велика таблица. Попробуйте EXPLAIN SELECT MAX(updated_at) ..., и вы увидите «Выберите оптимизированные таблицы». Об этой оптимизации читайте здесь: dev.mysql.com/doc/refman/5.7/en/explain-output.html
@BillKarwin: Не знаю, что вы имеете в виду под EXPLAIN ... |||| Но я согласен, добавление индекса делает SELECT MAX очень быстрым. Но влияет ли созданный индекс на производительность при вставке, например Вставить сразу 2,8 миллиона строк?
@Peter, да, конечно, у индексов есть накладные расходы. Вы должны решить, хотите ли вы оптимизировать для INSERT или оптимизировать для запросов, использующих индекс. Обычно создание индексов - хороший компромисс. Но мы не должны поддерживать индексы, которые не используются ни в одном из наших запросов.
@BillKarwin для удаленных записей. Я просто использую COUNT, чтобы вернуть количество строк, а также проверить это. Если запись удалена и никаких обновлений не производилось, то количество строк будет другим, а затем, если новая строка будет вставлена и соответствует предыдущему количеству после удаления строки, мы получим последнюю временную метку для нового строка создана. Мой запрос - SELECT COUNT(*) AS total_rows, UNIX_TIMESTAMP(MAX('updated_at')) AS updated FROM 'table', и затем я проверяю оба, чтобы установить флаг isDirty.
Тот же ответ здесь, с подсказками по производительности: stackoverflow.com/a/35362997/411189
Не уверен, что это будет интересно. Использование mysqlproxy между mysql и клиентами и использование сценария lua для обновления значения ключа в memcached в соответствии с интересными изменениями таблицы UPDATE, DELETE, INSERT было решением, которое я сделал совсем недавно. Если оболочка поддерживала хуки или триггеры в php, это могло быть проще. На данный момент ни одна из оберток этого не делает.
Самым простым было бы проверить временные метки файлов таблиц на диске. Например, вы можете проверить в своем каталоге данных
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.ht мл
@StackUnderflow, то, что вы сказали, неточно. Файлы ibd хранят данные и индексы для табличного пространства, которое содержит одну или несколько таблиц. Если данные хранятся в ibdata1, файла ibd не будет. Хранение данных в одном файле на таблицу было по умолчанию с MySQL 5.6 в 2013 году.
Анализ на уровне ОС:
Найдите, где хранится БД на диске:
grep datadir /etc/my.cnf
datadir=/var/lib/mysql
Проверить наличие последних изменений
cd /var/lib/mysql/{db_name}
ls -lrt
Должен работать со всеми типами баз данных.
Хотя есть общепринятый ответ, я не считаю его правильным. Это самый простой способ добиться того, что необходимо, но даже если он уже включен в InnoDB (на самом деле документы говорят вам, что вы все равно должны получить NULL ...), если вы читаете MySQL документы, даже в текущей версии (8.0) использование UPDATE_TIME является не тот вариант, потому что:
Timestamps are not persisted when the server is restarted or when the table is evicted from the InnoDB data dictionary cache.
Если я правильно понимаю (не могу проверить это на сервере прямо сейчас), метка времени сбрасывается после перезапуска сервера.
Что касается реальных (и, в общем, дорогостоящих) решений, у вас есть решение Билла Карвина с CURRENT_TIMESTAMP, и я хотел бы предложить другое, основанное на триггерах (я использую этот).
Вы начинаете с создания отдельной таблицы (или, может быть, у вас есть какая-то другая таблица, которая может использоваться для этой цели), которая будет работать как хранилище для глобальных переменных (здесь временных меток). Вам нужно сохранить два поля - имя таблицы (или любое другое значение, которое вы хотите сохранить здесь как идентификатор таблицы) и метку времени. После того, как он у вас есть, вы должны инициализировать его с этим идентификатором таблицы + датой начала (NOW () - хороший выбор :)).
Теперь вы переходите к таблицам, которые хотите наблюдать, и добавляете триггеры ПОСЛЕ INSERT / UPDATE / DELETE с помощью этой или аналогичной процедуры:
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
Я создал столбец по имени: update-at в phpMyAdmin и получил текущее время из метода Date () в моем коде (nodejs). при каждом изменении в таблице этот столбец фиксирует время изменений.
Добро пожаловать в StackOverflow! Пожалуйста, отредактируйте свой ответ, чтобы включить часть кода, который вы использовали, а также объяснение Почему, которое вы выбрали для этого. Этот вопрос почти Одиннадцать лет, и на него уже есть принятый и хорошо получивший ответ. Ваш ответ без кода или объяснения, скорее всего, будет отклонен или удален. Отредактируйте его, чтобы включить эти вещи, чтобы оправдать его место в этом посте.
а) Он покажет вам все таблицы и даты последнего обновления
SHOW TABLE STATUS FROM db_name;
затем вы можете дополнительно запросить конкретную таблицу:
SHOW TABLE STATUS FROM db_name like 'table_name';
б) Как и в приведенных выше примерах, вы не можете использовать сортировку по 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';
Я заставил это работать локально, но не на моем общем хосте для моего общедоступного веб-сайта (я думаю, проблема с правами).
SELECT last_update FROM mysql.innodb_table_stats WHERE table_name = 'yourTblName';
'2020-10-09 08:25:10'
MySQL 5.7.20-log on Win 8.1
Связанный: stackoverflow.com/questions/12563706/…