A flashback query permite ler o estado histórico de um cluster, banco de dados ou tabela em qualquer timestamp passado, sem restaurar um backup. Use esse recurso para auditar alterações de dados, investigar incidentes ou recuperar linhas modificadas ou excluídas acidentalmente.
Pré-requisitos
Antes de começar, verifique se você tem:
-
Um cluster PolarDB for MySQL que atenda a um dos seguintes requisitos de versão:
PolarDB for MySQL 8.0.2, versão de revisão 8.0.2.2.21 ou posterior
PolarDB for MySQL 8.0.1, versão de revisão 8.0.1.1.32 ou posterior
PolarDB for MySQL 5.7, versão de revisão 5.7.1.0.25 ou posterior
PolarDB for MySQL 5.6, versão de revisão 5.6.1.0.36 ou posterior
O parâmetro
innodb_backquery_enableativado na página Parameters do cluster. Esse parâmetro vem desativado por padrão.
Executar uma flashback query antes de ativarinnodb_backquery_enableretornaERROR 1815 (HY000): Internal error: the backquery_time set is out of range, too old.
Para obter instruções sobre como verificar a versão do cluster, consulte Consultar o número da versão.
Como funciona
O PolarDB armazena versões históricas de linhas nos logs de undo do InnoDB. Ao executar uma flashback query, o PolarDB percorre a cadeia de logs de undo de cada linha para reconstruir os dados conforme existiam no timestamp especificado.
A janela de tempo disponível para consultas é delimitada por innodb_backquery_window (padrão: 86400 segundos) e pela capacidade do log de undo definida por innodb_backquery_capacity_limit. Quando o limite de capacidade é atingido, a janela de tempo efetiva diminui. Uma janela de tempo maior aumenta o uso do tablespace de Undo e pode reduzir levemente a performance de escrita.
Sintaxe
Todas as flashback queries adicionam AS OF TIMESTAMP time_expr à referência da tabela.
Consulta de tabela única
SELECT column_name_list FROM table_name AS OF TIMESTAMP time_expr [alias] [WHERE ...];
Consulta de múltiplas tabelas
SELECT column_name_list
FROM table1_name AS OF TIMESTAMP time_expr [alias1],
table2_name AS OF TIMESTAMP time_expr [alias2]
[WHERE ...];
Consulta JOIN de múltiplas tabelas
SELECT column_name_list
FROM table1_name AS OF TIMESTAMP time_expr [alias1]
JOIN table2_name AS OF TIMESTAMP time_expr [alias2] ON join_cond1
JOIN table3_name AS OF TIMESTAMP time_expr [alias3] ON join_cond2
[WHERE ...];
Parâmetros
|
Parâmetro |
Obrigatório |
Descrição |
|
|
Sim |
Nomes das colunas a consultar |
|
|
Sim |
Nome da tabela |
|
|
Sim |
Timestamp pontual. Apenas expressões constantes são suportadas; nomes de colunas não são permitidos. Formatos aceitos: string datetime como |
|
|
Não |
Alias da tabela |
|
|
Sim (JOIN) |
Condição de JOIN |
Parâmetros
| Parâmetro | Tipo de dados | Descrição |
|---|---|---|
loose_innodb_backquery_enable | BOOL | Ativa ou desativa a flashback query. ON ativa o recurso; OFF o desativa (padrão). |
loose_innodb_backquery_window | ULONG | Janela de tempo (em segundos) na qual as flashback queries estão disponíveis. Intervalo: 1–604800. Padrão: 86400. Aumentar esse valor estende o alcance da consulta, mas também eleva o uso do tablespace de Undo e pode reduzir levemente a performance de escrita. |
loose_innodb_backquery_capacity_limit | ULONG | Capacidade máxima de log de Undo (em MB) reservada para flashback queries. Intervalo: 100–200.000.000. Padrão: 100.000.000. Ao atingir o limite, a janela de tempo efetiva diminui para permanecer dentro do limite de capacidade. |
Consultar dados históricos
Este exemplo demonstra como usar uma flashback query para visualizar dados antes da modificação.
Etapa 1: Preparar dados de teste
Em 2021-08-31 13:51, crie a tabela products e insira cinco linhas.
CREATE TABLE products (
prod_id BIGINT(10) PRIMARY KEY NOT NULL,
prod_name VARCHAR(20) NOT NULL,
cust_id BIGINT(10) NULL,
createtime DATETIME NOT NULL DEFAULT NOW()
);
INSERT INTO products (prod_id, prod_name, cust_id, createtime)
VALUES
(101, 'Book', 1, NOW()),
(102, 'Apple', 1, NOW()),
(103, 'Beef', 2, NOW()),
(104, 'Bread', 3, NOW()),
(105, 'Cheese', 4, NOW());
Etapa 2: Verificar os dados iniciais
SELECT * FROM products;
+---------+-----------+---------+---------------------+
| prod_id | prod_name | cust_id | createtime |
+---------+-----------+---------+---------------------+
| 101 | Book | 1 | 2021-08-31 13:51:22 |
| 102 | Apple | 1 | 2021-08-31 13:51:24 |
| 103 | Beef | 2 | 2021-08-31 13:51:26 |
| 104 | Bread | 3 | 2021-08-31 13:51:27 |
| 105 | Cheese | 4 | 2021-08-31 13:51:29 |
+---------+-----------+---------+---------------------+
5 rows in set (0.00 sec)
Etapa 3: Atualizar os dados
Em 2021-08-31 14:18, atualize duas linhas.
UPDATE products SET prod_id = 110, createtime = NOW() WHERE prod_name = 'Book';
UPDATE products SET prod_id = 119, createtime = NOW() WHERE prod_name = 'Apple';
A tabela agora apresenta o seguinte resultado:
+---------+-----------+---------+---------------------+
| prod_id | prod_name | cust_id | createtime |
+---------+-----------+---------+---------------------+
| 103 | Beef | 2 | 2021-08-31 13:51:26 |
| 104 | Bread | 3 | 2021-08-31 13:51:27 |
| 105 | Cheese | 4 | 2021-08-31 13:51:29 |
| 110 | Book | 1 | 2021-08-31 14:18:21 |
| 119 | Apple | 1 | 2021-08-31 14:18:22 |
+---------+-----------+---------+---------------------+
5 rows in set (0.00 sec)
Etapa 4: Consultar o snapshot histórico
Leia a tabela conforme ela existia em 2021-08-31 14:00:00 — após a criação das linhas, mas antes da atualização.
SELECT * FROM products AS OF TIMESTAMP '2021-08-31 14:00:00';
+---------+-----------+---------+---------------------+
| prod_id | prod_name | cust_id | createtime |
+---------+-----------+---------+---------------------+
| 101 | Book | 1 | 2021-08-31 13:51:22 |
| 102 | Apple | 1 | 2021-08-31 13:51:24 |
| 103 | Beef | 2 | 2021-08-31 13:51:26 |
| 104 | Bread | 3 | 2021-08-31 13:51:27 |
| 105 | Cheese | 4 | 2021-08-31 13:51:29 |
+---------+-----------+---------+---------------------+
5 rows in set (0.00 sec)
Limitações
Apenas consultas de tabela única. Evite usar flashback queries em consultas complexas com JOINs ou subconsultas. Embora a sintaxe suporte consultas de múltiplas tabelas, a performance degrada em joins complexos.
Chave primária obrigatória. As flashback queries dependem da chave primária. Consultas em índice secundário recorrem a varredura completa da tabela, o que reduz a performance.
-
Apenas leituras de snapshot. As flashback queries funcionam com leituras de snapshot. Leituras com bloqueio retornam o erro
This query in backquery is not a consistent read, please check.. Os seguintes tipos de instrução acionam leitura com bloqueio e não são suportados:-- S LOCK (REPEATABLE-READ isolation level or higher) INSERT INTO t1 SELECT * FROM t2 REPLACE INTO t1 SELECT * FROM t2 UPDATE t SET ... FROM (SELECT ...) AS h CREATE TABLE t1 AS SELECT * FROM t2 -- S LOCK UPDATE t1 JOIN (SELECT ...) t2 ON ... SET ... SELECT * FROM t LOCK IN SHARE MODE -- X LOCK SELECT * FROM t FOR UPDATE Operações DDL interrompem o acesso histórico. Após realizar uma operação DDL, não é possível executar flashback query nos dados anteriores à operação. Se você tentar consultar esses dados, o sistema poderá retornar o erro
Backquery primary key invisible.Limite de 100.000 versões por linha. Cada linha pode ter no máximo 100.000 versões históricas. Consultas em linhas que excedam esse limite retornam
record undo history version exceed limit.Tabelas excluídas. Uma flashback query consegue ler uma tabela excluída após a ativação do recurso, mas não lê tabelas excluídas antes da ativação.
Crescimento do log de undo. Ativar a flashback query faz o tablespace de Undo crescer dentro da janela de tempo configurada, especialmente em cenários com BLOB. Esse crescimento pode reduzir levemente a performance de escrita. Monitore o uso do tablespace de Undo e ajuste
innodb_backquery_windoweinnodb_backquery_capacity_limitpara equilibrar o alcance da consulta com a sobrecarga de armazenamento.