Como posso saber quando uma tabela do MySQL foi atualizada pela última vez?

176

No rodapé da minha página, gostaria de adicionar algo como "última atualização do xx / xx / 200x", sendo esta data a última vez que uma determinada tabela do mySQL foi atualizada.

Qual o melhor jeito pra fazer isso? Existe uma função para recuperar a última data atualizada? Devo acessar o banco de dados toda vez que precisar desse valor?

Raiva
fonte

Respostas:

276

Nas versões posteriores do MySQL, você pode usar o information_schemabanco de dados para informar quando outra tabela foi atualizada:

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

Obviamente, isso significa abrir uma conexão com o banco de dados.


Uma opção alternativa seria "tocar" em um arquivo específico sempre que a tabela MySQL for atualizada:

Em atualizações de banco de dados:

  • Abra seu arquivo de carimbo de data / hora no O_RDRWmodo
  • close isso de novo

ou alternativamente

  • use touch(), o equivalente PHP da utimes()função, para alterar o registro de data e hora do arquivo.

Na exibição da página:

  • use stat()para ler novamente a hora da modificação do arquivo.
Alnitak
fonte
9
Para obter detalhes, incluindo limitações do InnoDB, consulte dev.mysql.com/doc/refman/5.5/en/show-table-status.html ( show table statususos information_schema.tables)
KCD
11
O UPDATE_TIMEmétodo e o show table statusmétodo abaixo estão disponíveis apenas no mecanismo MyISAM, não no InnoDB. Embora isso esteja listado como um bug , é mencionado na Referência do MySQL 5.5 , que também diz que o file_per_tablemodo é um indicador não confiável do tempo de modificação.
idoimaging 25/09/12
5
Novamente, não funciona no InnoDB porque o mysql é um buggy: bugs.mysql.com/bug.php?id=14374
TMS
7
Para o MySQL 5.7.2+, ele também funciona para o InnoDB : "A partir do MySQL 5.7.2, UPDATE_TIME exibe um valor de carimbo de data / hora para o último UPDATE, INSERT ou DELETE executado nas tabelas do InnoDB que não são particionadas. Anteriormente, UPDATE_TIME exibia um valor NULL. para tabelas InnoDB ".
Peter V. Mørch
2
Isso não parece persistir na reinicialização para mim (na versão 5.7.11).
58

Eu não tenho banco de dados information_schema, usando o mysql versão 4.1.16, portanto, neste caso, você pode consultar isso:

SHOW TABLE STATUS FROM your_database LIKE 'your_table';

Ele retornará estas colunas:

| Nome Motor Versão | Row_format | Linhas | Comprimento médio 
| Comprimento_de_dados | Max_data_length | Comprimento do índice | Data_free | Incremento automático
| Create_time | Update_time | Hora da verificação | Agrupamento
| Soma de verificação | Criar_opções | Comentário

Como você pode ver, existe uma coluna chamada: " Update_time " que mostra o último horário de atualização para sua tabela .

Radu Maris
fonte
2
Ele também executar mais rápido (4x) então SELECT declaração
jmav
1
De fato, a maioria dos comandos SHOW como esse são simplesmente mapeados internamente para consultas Information_schema; portanto, essa resposta fornece exatamente os mesmos dados da resposta da Alnitak acima. E ajacian81 está correto - ele não funciona para o mecanismo de armazenamento padrão do MySQL, o InnoDB.
Bill Karwin
55

Estou surpreso que ninguém tenha sugerido acompanhar o tempo da última atualização por linha:

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;

Isso atualiza o carimbo de data / hora, mesmo que não o tenhamos mencionado em 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 |
+----+------+---------------------+

Agora você pode consultar o MAX ():

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

É certo que isso requer mais armazenamento (4 bytes por linha para TIMESTAMP).
Mas isso funciona para tabelas do InnoDB anteriores à versão 5.7.15 do MySQL, o que INFORMATION_SCHEMA.TABLES.UPDATE_TIMEnão acontece.

Bill Karwin
fonte
10
+1 Para mim, esta é a única resposta certa para esta pergunta. A questão realmente quer saber quando os dados relevantes são atualizados, e não quando uma tabela (que é irrelevante para o usuário) pode ou não ter sido alterada por qualquer motivo.
siride
23
Mas se você excluir um registro com um tempo de atualização menor, o MAX (updated_at) não funcionará.
Ammamon 31/03
3
@ Ammamon, é verdade, se você também precisar considerar exclusões, esta solução não reflete isso. Um gatilho para atualizar uma tabela de resumo pode ser a única solução abrangente, mas isso criaria um gargalo.
Bill Karwin
2
na maioria dos casos, saber que a exclusão não seria tão relevante e muitos aplicativos de nível superior não são realmente excluídos de muitas tabelas, mas simplesmente desativam um sinalizador para o equivalente.
Samuel Fullman
1
@Pavan, não há diferença, você está apenas confiando no comportamento padrão, e meu exemplo explicita a opção explicitamente. Mas a opção é idêntica ao comportamento padrão.
Bill Karwin
13

A coisa mais simples seria verificar o registro de data e hora dos arquivos da tabela no disco. Por exemplo, você pode verificar no seu diretório de dados

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

Isso deve fornecer a lista de todas as tabelas com a tabela na última vez em que foi modificada pela última vez.

user2654744
fonte
Realmente grande resposta desde UPDATE_TIME é NULL para todas as tabelas no meu caso (MariaDB)
Alexander Vasiljev
Os arquivos ibd armazenam apenas a estrutura da tabela. Por padrão, os dados são armazenados no ibdata1 para que o registro de data e hora do arquivo ibd não seja atualizado quando os dados forem alterados na tabela. https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
Stack Underflow
7

Para uma lista de alterações recentes na tabela, use este:

SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME
François Bourgeois
fonte
3
Por que todos os meus UPDATE_TIMEsão nulos? Qualquer ideia?
Metafaniel
5
Seu UPDATE_TIME é nulo porque você está usando o InnoDB em vez do MyISAM. O InnoDB é geralmente a melhor escolha, mas não suporta UPDATE_TIME.
Xaraxia 03/10
5

Eu criaria um gatilho que captura todas as atualizações / inserções / exclusões e grava timestamp na tabela personalizada, algo como tablename | timestamp

Só porque eu não gosto da ideia de ler diretamente as tabelas internas do sistema do servidor db

Mikhail
fonte
1
Esta parece ser uma boa solução para o MS SQL, porque não há UPDATE_TIMEcoluna como no MySQL.
315 Darcy
3

Embora exista uma resposta aceita, não acho que seja a correta. É a maneira mais simples de conseguir o que é necessário, mas mesmo se já estiver ativado no InnoDB (na verdade, os documentos dizem que você ainda deve receber NULL ...), se você ler os documentos do MySQL , mesmo na versão atual (8.0), usando UPDATE_TIME é Não é a opção certa, porque:

Os carimbos de data e hora não são mantidos quando o servidor é reiniciado ou quando a tabela é removida do cache do dicionário de dados do InnoDB.

Se eu entendi corretamente (não é possível verificá-lo em um servidor no momento), o carimbo de data e hora é redefinido após a reinicialização do servidor.

Quanto às soluções reais (e, bem, caras), você tem a solução de Bill Karwin com CURRENT_TIMESTAMP e eu gostaria de propor uma solução diferente, baseada em gatilhos (estou usando essa).

Você começa criando uma tabela separada (ou talvez você tenha alguma outra tabela que possa ser usada para essa finalidade) que funcionará como um armazenamento para variáveis ​​globais (aqui registros de data e hora). Você precisa armazenar dois campos - nome da tabela (ou qualquer valor que você queira manter aqui como ID da tabela) e carimbo de data e hora. Depois de ter, você deve inicializá-lo com este ID de tabela + data de início (NOW () é uma boa opção :)).

Agora, você passa para as tabelas que deseja observar e adiciona gatilhos APÓS INSERT / UPDATE / DELETE com este ou outro procedimento semelhante:

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
Ladrão de alma
fonte
1

Análise no nível do SO:

Encontre onde o banco de dados está armazenado no disco:

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

Verifique as modificações mais recentes

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

Deve funcionar em todos os tipos de banco de dados.

John McLean
fonte
0

Basta pegar a data do arquivo modificado no sistema de arquivos. Na minha língua isso é:

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

Resultado:

1/25/2013 06:04:10 AM
Steve Wood
fonte
6
parece com corte altamente não portátil, uma forma padrão que iria trabalhar em todos os lugares seria melhor
Tejesh Alimilli
0

Se você estiver executando o Linux, poderá usar o inotify para consultar a tabela ou o diretório do banco de dados. O inotify está disponível no PHP, node.js, perl e suspeito da maioria das outras linguagens. É claro que você deve ter instalado o inotify ou seu provedor de serviços de Internet o instalou. Um monte de ISP não vai.

bartonlp
fonte
2
Verificações de sistemas de arquivos não são úteis se o seu banco de dados está sendo executado em um servidor separado
Sam Dufel
0

Não tenho certeza se isso seria de algum interesse. Usar o mysqlproxy entre o mysql e os clientes e usar um script lua para atualizar um valor-chave no memcached de acordo com as mudanças interessantes na tabela UPDATE, DELETE, INSERT foi a solução que eu fiz recentemente. Se o wrapper suportasse ganchos ou gatilhos no php, isso poderia ter sido muito bom. Nenhum dos wrappers a partir de agora faz isso.

Jiju Thomas Mathew
fonte
0

Eu criei uma coluna pelo nome: update-at no phpMyAdmin e recebi a hora atual do método Date () no meu código (nodejs). com todas as alterações na tabela, essa coluna mantém o horário das alterações.

erva
fonte
1
Bem-vindo ao StackOverflow! Por favor edite sua resposta para incluir parte do código que você usou, bem como uma explicação de por que você escolheu para fazê-lo desta forma. Esta pergunta tem quase onze anos e já tem uma resposta aceita e bem-votada. Sua resposta, sem algum código ou explicação, provavelmente será votada ou excluída. A edição para incluir essas coisas ajudará a justificar seu lugar nesta postagem.
Das_Geek 12/11/19
0

a) Mostrará todas as tabelas e as datas da última atualização

SHOW TABLE STATUS FROM db_name;

então, você pode solicitar ainda uma tabela específica:

SHOW TABLE STATUS FROM db_name like 'table_name';

b) Como nos exemplos acima, você não pode usar a classificação em 'Update_time', mas usando SELECT, você pode:

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

para perguntar mais sobre determinada tabela:

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

Foi isso que fiz, espero que ajude.

<?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
fonte
2
Por que você usaria como aqui?
precisa
3
@WesleyMurch: a tag <font> está obsoleta.
siride
-9

Coloque em cache a consulta em uma variável global quando ela não estiver disponível.

Crie uma página da Web para forçar o recarregamento do cache quando você o atualizar.

Adicione uma chamada à página de recarga em seus scripts de implantação.

Kieveli
fonte
2
você não pode "armazenar em cache" variáveis ​​entre invocações independentes de uma página PHP sem assistência externa.
Alnitak