Mysql 5.6 no Debian 9: Eu tenho uma tabela muito grande em um servidor, serverA, e defini uma conexão do meu banco de dados no serverB para o banco de dados no serverA, usando create server connA ...
, e defini uma tabela no serverB que se conecta via connA a a mesa muito grande.
Quando consulto a tabela federada no serverB, funciona bem, se a consulta for processada rapidamente no serverA:
# on serverB:
mysql> select * from game_action where game_action_id=4;
+----------------+---------+---------+------------------+-------+--------+----------+---------------------+
| game_action_id | game_id | user_id | game_instance_id | type | amount | currency | created_timestamp |
+----------------+---------+---------+------------------+-------+--------+----------+---------------------+
| 4 | 1096 | 1 | 4 | WAGER | 1.00 | GBP | 2017-09-06 14:37:15 |
+----------------+---------+---------+------------------+-------+--------+----------+---------------------+
1 row in set (0.40 sec)
Mas (ainda no serverB):
mysql> select count(*) from game_action;
ERROR 2013 (HY000): Lost connection to MySQL server during query
A tabela é muito grande, então não é surpresa que demore muito para processar, mas eu preciso ser capaz de fazer coisas que demoram muito. Tivemos problemas com conexões caindo devido a tempos limite no passado, e eles têm sido muito difíceis de solucionar; alterar diferentes tempos limite em my.cnf não ajudou.
Qual é a melhor prática para solucionar esse problema específico?
Editar
A coisa muito estranha, eu sinto, é que não parece haver nenhuma variável de tempo limite que corresponda ao que eu vejo - eu configurei uma instância do mysql apenas para testar isso:
$ # On serverB:
$ time mysql -u root -pAtauseq01 gameiom -e "select count(*) from game_action;"
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
real 9m23.275s
user 0m0.014s
sys 0m0.004s
Então, cerca de 9 minutos de tempo limite, se for um tempo limite. Mas no servidor remoto (serverA):
mysql> show variables like "%timeout%";
+-------------------------------------+----------+
| Variable_name | Value |
+-------------------------------------+----------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| have_statement_timeout | YES |
| innodb_flush_log_at_timeout | 1 |
| innodb_lock_wait_timeout | 50 |
| innodb_print_lock_wait_timeout_info | OFF |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| rpl_stop_slave_timeout | 31536000 |
| slave_net_timeout | 3600 |
| thread_pool_idle_timeout | 60 |
| wait_timeout | 28800 |
+-------------------------------------+----------+
15 rows in set (0.00 sec)
Editar 2
Servidor A:
mysql> show variables like "flush%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| flush | OFF |
| flush_time | 0 |
+---------------+-------+
2 rows in set (0.00 sec)
Servidor B:
mysql> show variables like "flush%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| flush | OFF |
| flush_time | 0 |
+---------------+-------+
2 rows in set (0.01 sec)
Editar 3
No servidorA:
mysql> pager grep -v PARTITION
PAGER set to 'grep -v PARTITION'
mysql> show create table game_action\G
*************************** 1. row ***************************
Table: game_action
Create Table: CREATE TABLE `game_action` (
`game_action_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`game_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`game_instance_id` bigint(20) unsigned DEFAULT NULL,
`type` varchar(15) NOT NULL,
`amount` decimal(18,2) NOT NULL,
`currency` varchar(15) NOT NULL,
`created_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`game_action_id`,`created_timestamp`),
KEY `GA_IX01` (`game_id`),
KEY `GA_IX02` (`user_id`),
KEY `GA_IX03` (`game_instance_id`),
KEY `game_action_created_timestamp` (`created_timestamp`),
KEY `ga_id_cur_tstmp` (`game_id`,`currency`,`created_timestamp`)
) ENGINE=InnoDB AUTO_INCREMENT=1064199804 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
No servidor B:
mysql> show create table game_action\G
*************************** 1. row ***************************
Table: game_action
Create Table: CREATE TABLE `game_action` (
`game_action_id` bigint unsigned NOT NULL AUTO_INCREMENT,
`game_id` int NOT NULL,
`user_id` int NOT NULL,
`game_instance_id` bigint unsigned DEFAULT NULL,
`type` varchar(15) NOT NULL,
`amount` decimal(18,2) NOT NULL,
`currency` varchar(15) NOT NULL,
`created_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`game_action_id`,`created_timestamp`),
KEY `GA_IX01` (`game_id`),
KEY `GA_IX02` (`user_id`),
KEY `GA_IX03` (`game_instance_id`),
KEY `game_action_created_timestamp` (`created_timestamp`),
KEY `ga_id_cur_tstmp` (`game_id`,`currency`,`created_timestamp`)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci CONNECTION='gameiom'
1 row in set (0.00 sec)
Se você for do prompt de comando do MySQL, SET GLOBAL NET_READ_TIMEOUT=3600; no Servidor A e no Servidor B, pode ser longo o suficiente para enviar todas as 1 milhão de linhas de dados para o Servidor B da tabela.
Observações, A) Os dois SHOW CREATE TABLES apresentam algumas diferenças significativas na estratégia CHARSET e COLLATE. Não tenho certeza de quão significativo isso é, mas pode ser importante.
A próxima URL é para o documento de detalhes do mecanismo FEDERADO por Baron Schwartz de anos atrás. Ele documentou muitos detalhes detalhados de como testou nos primeiros dias da disponibilidade do motor. https://www.xaprb.com/blog/2007/01/29/mysqls-federated-storage-engine-part-1/
e https://www.xaprb.com/blog/2007/01/31/mysqls -motor de armazenamento federado-parte-2/
A próxima URL é para uma possível resolução de conexão perdida do MySQL - https://dev.mysql.com/doc/refman/5.7/en/error-lost-connection.html