No momento, estou tentando criar um evento agendado no MySQL para limpar os logs binários toda semana.
A instrução create event é a seguinte:
CREATE EVENT purgebinlogs
ON SCHEDULE EVERY 1 WEEK
STARTS CONCAT(CURRENT_DATE + INTERVAL 7 - WEEKDAY(CURRENT_DATE) DAY,' 01:00:00')
DO
PURGE BINARY LOGS BEFORE DATE_SUB( NOW( ), INTERVAL 7 DAY);
Deve ser executado toda segunda-feira à 01:00. No entanto, se eu consultar a tabela mysql.event, obtenho a seguinte saída:
mysql> select * from mysql.event\G
*************************** 1. row ***************************
db: mysql
name: purgebinlogs
body: PURGE BINARY LOGS BEFORE DATE_SUB( NOW( ), INTERVAL 7 DAY)
definer: root@localhost
execute_at: NULL
interval_value: 7
interval_field: WEEK
created: 2015-03-13 17:45:20
modified: 2015-03-13 17:51:43
last_executed: NULL
starts: 2015-03-16 07:00:00
ends: NULL
status: ENABLED
on_completion: DROP
sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
comment:
originator: 1
time_zone: SYSTEM
character_set_client: cp850
collation_connection: cp850_general_ci
db_collation: utf8_general_ci
body_utf8: PURGE BINARY LOGS BEFORE DATE_SUB( NOW( ), INTERVAL 7 DAY)
Como você pode ver, a coluna inicial diz:
início: 2015-03-16 07:00:00
A data está OK, mas a hora... Deve ser 01:00 e não 07:00
Acho que isso pode ser um problema de fuso horário, porque meu fuso horário é "-06:00"
mysql> show global variables like 'time_z%';
+------------------+----------+
| Variable_name | Value |
+------------------+----------+
| time_zone | -06:00 |
+------------------+----------+
2 rows in set, 1 warning (0.01 sec)
mysql> SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
+--------------------------------+
| TIMEDIFF(NOW(), UTC_TIMESTAMP) |
+--------------------------------+
| -06:00:00 |
+--------------------------------+
1 row in set (0.00 sec)
Mas não consigo adivinhar como consertar isso. Quero executar o evento agendado às 01:00
EDITAR
ao consultar information_schema.events ele exibe as informações corretas
mysql> select * from information_schema.events\G
*************************** 1. row ***************************
EVENT_CATALOG: def
EVENT_SCHEMA: mysql
EVENT_NAME: purgebinlogs
DEFINER: root@localhost
TIME_ZONE: SYSTEM
EVENT_BODY: SQL
EVENT_DEFINITION: PURGE BINARY LOGS BEFORE DATE_SUB( NOW( ), INTERVAL 7 DAY)
EVENT_TYPE: RECURRING
EXECUTE_AT: NULL
INTERVAL_VALUE: 1
INTERVAL_FIELD: WEEK
SQL_MODE: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
STARTS: 2015-03-16 01:00:00
ENDS: NULL
STATUS: ENABLED
ON_COMPLETION: NOT PRESERVE
CREATED: 2015-03-13 17:45:20
LAST_ALTERED: 2015-03-13 17:56:32
LAST_EXECUTED: NULL
EVENT_COMMENT:
ORIGINATOR: 1
CHARACTER_SET_CLIENT: cp850
COLLATION_CONNECTION: cp850_general_ci
DATABASE_COLLATION: utf8_general_ci
Então eu acho que mysql.event exibe informações no horário UTC não no fuso horário local
EDITAR
Conforme sugerido por @Rick James, alterei dinamicamente o valor de expire_logs_days com o seguinte comando:
set global expire_logs_days=7
Mas parece que não está funcionando....
mysql> show global variables like 'expire%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| expire_logs_days | 7 |
+------------------+-------+
No entanto, se eu listar os arquivos binlog, obtenho a seguinte lista:
Mar 5 19:30 mysql56_bin.000001
Mar 5 19:30 mysql56_bin.000002
Mar 10 13:53 mysql56_bin.000003
Mar 11 11:59 mysql56_bin.000004
Mar 11 17:44 mysql56_bin.000005
Mar 12 12:53 mysql56_bin.000006
Mar 12 12:58 mysql56_bin.000007
Mar 12 13:02 mysql56_bin.000008
Mar 12 13:07 mysql56_bin.000009
Mar 12 13:12 mysql56_bin.000010
Mar 12 13:16 mysql56_bin.000011
Mar 12 13:20 mysql56_bin.000012
Mar 12 13:24 mysql56_bin.000013
Mar 17 10:38 mysql56_bin.000014
Mar 17 18:27 mysql56_bin.000015
Mar 17 18:28 mysql56_bin.000016
Mar 17 18:28 mysql56_bin.index
Como você pode ver, há binlogs com mais de uma semana atrás.
Parece que
expire_logs_days 7
seria muito mais simples.8.0 está se movendo em direção a
binlog_expire_logs_seconds
.Eu tenho ainda outro método para limpar logs automaticamente no mestre com base no que um escravo replicou.
Isenção de responsabilidade: não tenho esta solução em produção há muito tempo, portanto, prossiga por sua conta e risco
O shell script a seguir deve ser executado no servidor mestre. Ele assume que o escravo pode ser acessado via SSH. Você poderia facilmente adaptar isso a outros cenários.
Eu executo esse script em uma
cron
programação diária para garantir que os logs sejam limpos regularmente.Olá, fiz um script que limpa logs binários na replicação mestre/escravo do mysql.
Assim sempre tenho cca. 50 logs binários. Eu tenho isso no servidor escravo no crontab e o executo a cada poucas horas.
Felicidades
Para o MySQL 8 existe outra opção:
binlog_expire_logs_seconds
- infelizmente não encontro uma entrada na documentação. Somente esta entrada de tarefa .Adicione esta configuração ao
/etc/my.cnf
arquivo [Linux version].Além disso,
expire_logs_days
está obsoleto no MYSQL 8 .Tente com variável global
Para mais detalhes leia aqui
definir binlog_expire_logs_seconds seria muito mais simples
mostrar variáveis globais como 'binlog_expire_logs_seconds'; SET GLOBAL binlog_expire_logs_seconds = 604800;
'expire_logs_days' agora está depreciado no Mysql8 Em vez disso, use 'binlog_expire_logs_seconds'.
Depende do seu requisito, mas em geral use a instrução abaixo (altere o valor dos segundos de acordo com as necessidades do seu aplicativo): SET GLOBAL binlog_expire_logs_seconds=3600;