Recuperação da Comunidade Contra Ataque

9
133
views

Contra Ataque

A equipa WebTuga dedica grande parte do seu tempo a discutir ideias, partilhar conhecimento, ajudar os seus clientes e a desenvolver projectos internos.

Quando verificamos que um projecto interessante necessita do nosso apoio, fazemos tudo o que está ao nosso alcance para fornecermos a ajuda necessária de forma a que este projecto possa continuar a crescer e evoluir. Foi exactamente o que aconteceu com a comunidade Contra Ataque.

Antes de mais, gostaria de dar a conhecer esta comunidade e qual o seu tema principal. O Contra Ataque é uma comunidade com cerca de 5 anos de existência, constituída por mais de 6.500 membros e com uma participação de mais de 1 milhão e 300 mil mensagens num fórum de discussão dedicado a Futebol e outros desportos.

Com um crescimento gradual bastante acentuado, esta comunidade começou a ter problemas técnicos no anterior provedor de alojamento devido ao consumo excessivo de recursos no servidor derivado não só à grandiosidade do projecto mas também à falta de manutenção da base de dados e da plataforma que suporta o fórum de discussão.

Ao saber desta situação, a WebTuga disponibilizou-se prontamente para fornecer qualquer tipo de suporte a nível de infra-estrutura de forma a dar continuidade ao projecto.

Dessa forma chegamos a um acordo com o Ricardo Miguel, responsável pela comunidade Contra Ataque, para que a comunidade fosse transferida para os nossos servidores, sendo este projecto apoiado e patrocinado pela WebTuga.

De forma a recolher informação técnica acerca do consumo de recursos e estado actual do site da comunidade para preparação da migração, analisamos o conteúdo do site no servidor do provedor antigo.

Após alguns minutos de análise, verificamos que a maior percentagem de utilização do espaço na conta de alojamento do site estava a ser provocada devido ao tamanho de uma das tabelas da base de dados MySql do Invision Power Board (plataforma do fórum).

Esta tabela era irrelevante, uma vez que guardava apenas informações relativas ao acesso dos motores de busca (spiders/search engine bots, “googlebot“, etc) e estava a ocupar cerca de 4GB.

Após termos informado o Ricardo Miguel desta situação, ele procedeu à limpeza da tabela através das ferramentas disponibilizadas pelo IPB.

O processo de limpeza de logs feito através das ferramentas do IPB é equivalente ao seguinte comando SQL para limpeza dos registos da tabela ibf_spider_logs:

1
TRUNCATE ibf_spider_logs;

Devido ao tamanho anormal da tabela ibf_spider_logs, a query mysql resultante da execução da ferramenta de limpeza de logs começou por consumir bastantes recursos no servidor, tendo a conta sido suspensa pelo provedor anterior.

A interrupção do servidor MySql nesta fase, terá levado a que as tabelas em uso tivessem ficado inacessíveis e/ou corrompidas, o que levou à impossibilidade de aceder aos tópicos do fórum.

Após se verificar esta situação, foi pedido pelo Ricardo Miguel à empresa de alojamento anterior o restauro de um backup diário para que pudesse ser restabelecido o fórum. Uma vez que o backup diário continha apenas dados parciais da base de dados, o fórum ficou sem a tabela de tópicos (ibf_topics), sendo assim impossível aceder aos posts/página de tópicos mesmo com o restauro do backup.

Tentamos restaurar o backup diário no nosso servidor, tendo havido alguns problemas devido ao tamanho da base de dados que fez com que o processo de restauro fosse demorado e também devido ao facto do charset da mesma estar incorrecto.

De forma a ultrapassar estes dois problemas restauramos a conta manualmente através dos ficheiros do backup gerado pelo cPanel e utilizando um software chamado PilotEdit Lite abrimos o ficheiro .sql da base de dados para remover as entradas da tabela ibf_spider_logs que ainda se encontravam no backup.

O PilotEdit Lite é um programa excelente para a edição de ficheiros de texto com mais de 4GBs, facilitando-nos assim a vida na limpeza do “lixo” existente na base de dados.

Após a limpeza do ficheiro sql, utilizamos o pacote iconv para converter o charset do ficheiro para utf-8, sendo possível assim restaurar o conteúdo da base de dados sem problemas de caracteres.

Infelizmente, só após ter sido restaurado este ficheiro SQL com a base de dados é que reparamos que o backup fornecido da base de dados não continha todas as tabelas necessárias para o funcionamento da plataforma. Apenas estavam incluídas as tabelas até à tabela em questão (ibf_spider_logs), sendo impossível da nossa parte restaurar todas as informações no fórum e reestabelecer o seu funcionamento normal, uma vez que o backup estava incompleto.

A pedido do Ricardo Miguel, foi-nos fornecido posteriormente os restantes backups existentes da conta de alojamento do servidor antigo, incluindo um backup mensal e e um backup semanal.

No entanto e para azar de todos, após terem sido exportadas as base de dados de ambas as cópias de segurança e abertas com o PilotEdit Lite, a situação relatada anteriormente ocorria em ambos os casos, uma vez que o backup da base de dados no antigo provedor falhava sempre na exportação do conteúdo da tabela ibf_spider_logs, não continuando a exportação das restantes tabelas e respectivo conteúdo.

Pedimos que fosse verificada a existência de backups adicionais no entanto os backups feitos pelo Ricardo Miguel também não tinham qualquer conteúdo na base de dados e a havia ausência de qualquer outra cópia de segurança dos dados do site ou base de dados.

Contra Ataque

Infelizmente nesta fase já não existiam grandes esperanças da nossa equipa para que fosse encontrada uma solução a este problema, uma vez que não haviam dados para restaurar.

Chegamos a pensar que fosse impossível restaurar o fórum e lamentar o facto de que se iria perder uma comunidade com 5 anos de trabalho criado por todos os seus utilizadores.

Apesar das poucas esperanças, a equipa WebTuga não desistiu de encontrar solução. Seria bastante frustrante para nós ver uma comunidade com 5 anos e mais de 1 milhão de posts desaparecer de um momento para o outro sem que pudéssemos fazer nada para a sua “salvação”.

Entramos em contacto com o suporte oficial da Invision Power Board de forma a obter informações sobre uma possível reconstrução da tabela ibf_topics, no entanto não nos foi fornecida qualquer informação técnica relativa a este assunto visto não ser a WebTuga a detentora da licença de software da plataforma para o site em questão.

Tentamos de seguida obter informações acerca de quais as tabelas que estariam em falta no backup e que tinham sido perdidas. Através de um pacote de instalação da versão em questão do IPB, verificamos nos ficheiros de instalação as instruções SQL executadas na instalação da plataforma.

Desta forma chegamos à conclusão de que as tabelas em falta na cópia de segurança da base de dados seriam as seguintes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ibf_subscription_currency
ibf_subscription_extra
ibf_subscription_logs
ibf_subscription_methods
ibf_subscription_trans
ibf_subscriptions
ibf_task_logs
ibf_task_manager
ibf_templates_diff_import
ibf_template_diff_session
ibf_template_diff_changes
ibf_titles
ibf_topic_markers
ibf_topic_mmod
ibf_topic_ratings
ibf_topic_views
ibf_topics
ibf_topics_read
ibf_tracker
ibf_upgrade_history
ibf_validating
ibf_voters
ibf_warn_logs

Para aqueles que estão a ler este artigo e não tem grandes conhecimentos técnicos, as tabelas guardam informação da base de dados do fórum.

Neste caso, a tabela importante e necessária para o funcionamento do fórum era a ibf_topics que continha informação acerca dos títulos dos tópicos, a categoria a que o tópico pertencia, entre outros dados menos relevantes.

Através do pacote de instalação do IPB, conseguimos saber qual a estrutura das tabelas acima indicadas e recorrendo a um conjunto de queries MySql, recriamos as tabelas sem qualquer conteúdo. Poderá verificar as instruções SQL abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
CREATE TABLE ibf_subscription_currency (
  subcurrency_code VARCHAR(10) NOT NULL DEFAULT '',
  subcurrency_desc VARCHAR(250) NOT NULL DEFAULT '',
  subcurrency_exchange DECIMAL(16,8) NOT NULL DEFAULT '0.00000000',
  subcurrency_default tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY  (subcurrency_code)
);

CREATE TABLE ibf_subscription_extra (
  subextra_id SMALLINT(5) NOT NULL AUTO_INCREMENT,
  subextra_sub_id SMALLINT(5) NOT NULL DEFAULT '0',
  subextra_method_id SMALLINT(5) NOT NULL DEFAULT '0',
  subextra_product_id VARCHAR(250) NOT NULL DEFAULT '0',
  subextra_can_upgrade tinyint(1) NOT NULL DEFAULT '0',
  subextra_recurring tinyint(1) NOT NULL DEFAULT '0',
  subextra_custom_1 text NULL,
  subextra_custom_2 text NULL,
  subextra_custom_3 text NULL,
  subextra_custom_4 text NULL,
  subextra_custom_5 text NULL,
  PRIMARY KEY  (subextra_id)
);

CREATE TABLE ibf_subscription_logs (
  sublog_id INT(10) NOT NULL AUTO_INCREMENT,
  sublog_date INT(10) NOT NULL DEFAULT '0',
  sublog_member_id mediumint(8) NOT NULL DEFAULT '0',
  sublog_transid INT(10) NOT NULL DEFAULT '0',
  sublog_ipaddress VARCHAR(16) NOT NULL DEFAULT '',
  sublog_data text NULL,
  sublog_postdata text NULL,
  PRIMARY KEY  (sublog_id)
);

CREATE TABLE ibf_subscription_methods (
  submethod_id SMALLINT(5) NOT NULL AUTO_INCREMENT,
  submethod_title VARCHAR(250) NOT NULL DEFAULT '',
  submethod_name VARCHAR(20) NOT NULL DEFAULT '',
  submethod_email VARCHAR(250) NOT NULL DEFAULT '',
  submethod_sid text NULL,
  submethod_custom_1 text NULL,
  submethod_custom_2 text NULL,
  submethod_custom_3 text NULL,
  submethod_custom_4 text NULL,
  submethod_custom_5 text NULL,
  submethod_is_cc tinyint(1) NOT NULL DEFAULT '0',
  submethod_is_auto tinyint(1) NOT NULL DEFAULT '0',
  submethod_desc text NULL,
  submethod_logo text NULL,
  submethod_active tinyint(1) NOT NULL DEFAULT '0',
  submethod_use_currency VARCHAR(10) NOT NULL DEFAULT 'USD',
  PRIMARY KEY  (submethod_id)
);

CREATE TABLE ibf_subscription_trans (
  subtrans_id INT(10) NOT NULL AUTO_INCREMENT,
  subtrans_sub_id SMALLINT(5) NOT NULL DEFAULT '0',
  subtrans_member_id mediumint(8) NOT NULL DEFAULT '0',
  subtrans_old_group SMALLINT(5) NOT NULL DEFAULT '0',
  subtrans_paid DECIMAL(10,2) NOT NULL DEFAULT '0.00',
  subtrans_cumulative DECIMAL(10,2) NOT NULL DEFAULT '0.00',
  subtrans_method VARCHAR(20) NOT NULL DEFAULT '',
  subtrans_start_date INT(11) NOT NULL DEFAULT '0',
  subtrans_end_date INT(11) NOT NULL DEFAULT '0',
  subtrans_state VARCHAR(200) NOT NULL DEFAULT '',
  subtrans_trxid VARCHAR(200) NOT NULL DEFAULT '',
  subtrans_subscrid VARCHAR(200) NOT NULL DEFAULT '',
  subtrans_currency VARCHAR(10) NOT NULL DEFAULT 'USD',
  PRIMARY KEY  (subtrans_id)
);

CREATE TABLE ibf_subscriptions (
  sub_id SMALLINT(5) NOT NULL AUTO_INCREMENT,
  sub_title VARCHAR(250) NOT NULL DEFAULT '',
  sub_desc text NULL,
  sub_new_group mediumint(8) NOT NULL DEFAULT '0',
  sub_length SMALLINT(5) NOT NULL DEFAULT '1',
  sub_unit CHAR(2) NOT NULL DEFAULT 'm',
  sub_cost DECIMAL(10,2) NOT NULL DEFAULT '0.00',
  sub_run_module VARCHAR(250) NOT NULL DEFAULT '',
  PRIMARY KEY  (sub_id)
);

CREATE TABLE ibf_task_logs (
  log_id INT(10) NOT NULL AUTO_INCREMENT,
  log_title VARCHAR(255) NOT NULL DEFAULT '',
  log_date INT(10) NOT NULL DEFAULT '0',
  log_ip VARCHAR(16) NOT NULL DEFAULT '0',
  log_desc text NULL,
  PRIMARY KEY  (log_id)
);

CREATE TABLE ibf_task_manager (
  task_id INT(10) NOT NULL AUTO_INCREMENT,
  task_title VARCHAR(255) NOT NULL DEFAULT '',
  task_file VARCHAR(255) NOT NULL DEFAULT '',
  task_next_run INT(10) NOT NULL DEFAULT '0',
  task_week_day tinyint(1) NOT NULL DEFAULT '-1',
  task_month_day SMALLINT(2) NOT NULL DEFAULT '-1',
  task_hour SMALLINT(2) NOT NULL DEFAULT '-1',
  task_minute SMALLINT(2) NOT NULL DEFAULT '-1',
  task_cronkey VARCHAR(32) NOT NULL DEFAULT '',
  task_log tinyint(1) NOT NULL DEFAULT '0',
  task_description text NULL,
  task_enabled tinyint(1) NOT NULL DEFAULT '1',
  task_key VARCHAR(30) NOT NULL DEFAULT '',
  task_safemode tinyint(1) NOT NULL DEFAULT '0',
  task_locked INT(10) NOT NULL DEFAULT '0',
  PRIMARY KEY  (task_id),
  KEY task_next_run (task_next_run)
);

CREATE TABLE ibf_templates_diff_import (
 diff_key         VARCHAR(255) NOT NULL,
 diff_func_group     VARCHAR(150) NOT NULL,
 diff_func_name      VARCHAR(250) NOT NULL,
 diff_func_data      TEXT NULL,
 diff_func_content   MEDIUMTEXT NULL,
 diff_session_id     INT(10) NOT NULL DEFAULT '0',
 PRIMARY KEY (diff_key),
 KEY diff_func_group (diff_func_group),
 KEY diff_func_name (diff_func_name)
);

CREATE TABLE ibf_template_diff_session (
 diff_session_id           INT(10) NOT NULL AUTO_INCREMENT,
 diff_session_togo         INT(10) NOT NULL DEFAULT '0',
 diff_session_done         INT(10) NOT NULL DEFAULT '0',
 diff_session_updated      INT(10) NOT NULL DEFAULT '0',
 diff_session_title        VARCHAR(255) NOT NULL DEFAULT '',
 diff_session_ignore_missing INT(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (diff_session_id)
);

CREATE TABLE ibf_template_diff_changes (
 diff_change_key        VARCHAR(255) NOT NULL,
 diff_change_func_group VARCHAR(150) NOT NULL,
 diff_change_func_name  VARCHAR(250) NOT NULL,
 diff_change_content    MEDIUMTEXT NULL,
 diff_change_type    INT(1) NOT NULL DEFAULT '0',
 diff_session_id         INT(10) NOT NULL DEFAULT '0',
 PRIMARY KEY (diff_change_key),
 KEY diff_change_func_group (diff_change_func_group),
 KEY diff_change_type (diff_change_type)
);

CREATE TABLE ibf_titles (
  id SMALLINT(5) NOT NULL AUTO_INCREMENT,
  posts INT(10) DEFAULT NULL,
  title VARCHAR(128) DEFAULT NULL,
  pips VARCHAR(128) DEFAULT NULL,
  PRIMARY KEY  (id),
  KEY posts (posts)
);

CREATE TABLE ibf_topic_markers (
  marker_member_id INT(8) NOT NULL DEFAULT '0',
  marker_forum_id INT(10) NOT NULL DEFAULT '0',
  marker_last_update INT(10) NOT NULL DEFAULT '0',
  marker_unread SMALLINT(5) NOT NULL DEFAULT '0',
  marker_topics_read text NULL,
  marker_last_cleared INT(10) NOT NULL DEFAULT '0',
  UNIQUE KEY marker_forum_id (marker_forum_id,marker_member_id),
  KEY marker_member_id (marker_member_id)
);

CREATE TABLE ibf_topic_mmod (
  mm_id SMALLINT(5) NOT NULL AUTO_INCREMENT,
  mm_title VARCHAR(250) NOT NULL DEFAULT '',
  mm_enabled tinyint(1) NOT NULL DEFAULT '0',
  topic_state VARCHAR(10) NOT NULL DEFAULT 'leave',
  topic_pin VARCHAR(10) NOT NULL DEFAULT 'leave',
  topic_move SMALLINT(5) NOT NULL DEFAULT '0',
  topic_move_link tinyint(1) NOT NULL DEFAULT '0',
  topic_title_st VARCHAR(250) NOT NULL DEFAULT '',
  topic_title_end VARCHAR(250) NOT NULL DEFAULT '',
  topic_reply tinyint(1) NOT NULL DEFAULT '0',
  topic_reply_content text NULL,
  topic_reply_postcount tinyint(1) NOT NULL DEFAULT '0',
  mm_forums text NULL,
  topic_approve tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY  (mm_id)
);

CREATE TABLE ibf_topic_ratings (
  rating_id INT(10) NOT NULL AUTO_INCREMENT,
  rating_tid INT(10) NOT NULL DEFAULT '0',
  rating_member_id mediumint(8) NOT NULL DEFAULT '0',
  rating_value SMALLINT(6) NOT NULL DEFAULT '0',
  rating_ip_address VARCHAR(16) NOT NULL DEFAULT '',
  PRIMARY KEY  (rating_id),
  KEY rating_tid (rating_tid,rating_member_id)
);

CREATE TABLE ibf_topic_views (
  views_tid INT(10) NOT NULL DEFAULT '0'
);

CREATE TABLE ibf_topics (
  tid INT(10) NOT NULL AUTO_INCREMENT,
  title VARCHAR(250) NOT NULL DEFAULT '',
  description VARCHAR(70) DEFAULT NULL,
  state VARCHAR(8) DEFAULT NULL,
  posts INT(10) DEFAULT NULL,
  starter_id mediumint(8) NOT NULL DEFAULT '0',
  start_date INT(10) DEFAULT NULL,
  last_poster_id mediumint(8) NOT NULL DEFAULT '0',
  last_post INT(10) DEFAULT NULL,
  icon_id tinyint(2) DEFAULT NULL,
  starter_name VARCHAR(32) DEFAULT NULL,
  last_poster_name VARCHAR(32) DEFAULT NULL,
  poll_state VARCHAR(8) DEFAULT NULL,
  last_vote INT(10) DEFAULT NULL,
  views INT(10) DEFAULT NULL,
  forum_id SMALLINT(5) NOT NULL DEFAULT '0',
  approved tinyint(1) NOT NULL DEFAULT '0',
  author_mode tinyint(1) DEFAULT NULL,
  pinned tinyint(1) DEFAULT NULL,
  moved_to VARCHAR(64) DEFAULT NULL,
  total_votes INT(5) NOT NULL DEFAULT '0',
  topic_hasattach SMALLINT(5) NOT NULL DEFAULT '0',
  topic_firstpost INT(10) NOT NULL DEFAULT '0',
  topic_queuedposts INT(10) NOT NULL DEFAULT '0',
  topic_open_time INT(10) NOT NULL DEFAULT '0',
  topic_close_time INT(10) NOT NULL DEFAULT '0',
  topic_rating_total SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
  topic_rating_hits SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
  PRIMARY KEY  (tid),
  KEY topic_firstpost (topic_firstpost),
  KEY last_post (forum_id,pinned,last_post),
  KEY forum_id (forum_id,pinned,approved),
  KEY starter_id (starter_id, forum_id, approved),
  KEY last_post_sorting (last_post,forum_id)
);

CREATE TABLE ibf_topics_read (
  read_tid INT(10) NOT NULL DEFAULT '0',
  read_mid mediumint(8) NOT NULL DEFAULT '0',
  read_date INT(10) NOT NULL DEFAULT '0',
  UNIQUE KEY read_tid_mid (read_tid,read_mid)
);

CREATE TABLE ibf_tracker (
  trid mediumint(8) NOT NULL AUTO_INCREMENT,
  member_id mediumint(8) NOT NULL DEFAULT '0',
  topic_id INT(10) NOT NULL DEFAULT '0',
  start_date INT(10) DEFAULT NULL,
  last_sent INT(10) NOT NULL DEFAULT '0',
  topic_track_type VARCHAR(100) NOT NULL DEFAULT 'delayed',
  PRIMARY KEY  (trid),
  KEY topic_id (topic_id)
);

CREATE TABLE ibf_upgrade_history (
  upgrade_id INT(10) NOT NULL AUTO_INCREMENT,
  upgrade_version_id INT(10) NOT NULL DEFAULT '0',
  upgrade_version_human VARCHAR(200) NOT NULL DEFAULT '',
  upgrade_date INT(10) NOT NULL DEFAULT '0',
  upgrade_mid INT(10) NOT NULL DEFAULT '0',
  upgrade_notes text NULL,
  PRIMARY KEY  (upgrade_id)
);

CREATE TABLE ibf_validating (
  vid VARCHAR(32) NOT NULL DEFAULT '',
  member_id mediumint(8) NOT NULL DEFAULT '0',
  real_group SMALLINT(3) NOT NULL DEFAULT '0',
  temp_group SMALLINT(3) NOT NULL DEFAULT '0',
  entry_date INT(10) NOT NULL DEFAULT '0',
  coppa_user tinyint(1) NOT NULL DEFAULT '0',
  lost_pass tinyint(1) NOT NULL DEFAULT '0',
  new_reg tinyint(1) NOT NULL DEFAULT '0',
  email_chg tinyint(1) NOT NULL DEFAULT '0',
  ip_address VARCHAR(16) NOT NULL DEFAULT '0',
  user_verified tinyint(1) NOT NULL DEFAULT '0',
  prev_email VARCHAR(150) NOT NULL DEFAULT '0',
  PRIMARY KEY  (vid),
  KEY new_reg (new_reg)
);

CREATE TABLE ibf_voters (
  vid INT(10) NOT NULL AUTO_INCREMENT,
  ip_address VARCHAR(16) NOT NULL DEFAULT '',
  vote_date INT(10) NOT NULL DEFAULT '0',
  tid INT(10) NOT NULL DEFAULT '0',
  member_id VARCHAR(32) DEFAULT NULL,
  forum_id SMALLINT(5) NOT NULL DEFAULT '0',
  KEY (tid),
  PRIMARY KEY  (vid)
);

CREATE TABLE ibf_warn_logs (
  wlog_id INT(10) NOT NULL AUTO_INCREMENT,
  wlog_mid mediumint(8) NOT NULL DEFAULT '0',
  wlog_notes text NULL,
  wlog_contact VARCHAR(250) NOT NULL DEFAULT 'none',
  wlog_contact_content text NULL,
  wlog_date INT(10) NOT NULL DEFAULT '0',
  wlog_type VARCHAR(6) NOT NULL DEFAULT 'pos',
  wlog_addedby mediumint(8) NOT NULL DEFAULT '0',
  PRIMARY KEY  (wlog_id)
);

Após algumas horas a analisar os campos vazios das tabelas, com muito café e tabaco à mistura, chegamos à conclusão de que poderíamos reconstruir a tabela ibf_topics com dados fictícios (Exemplo: Titulo dos Tópicos: “Tópico #1”, “Tópico #2”, “Tópico #3”, etc) de forma a colocar o fórum funcional novamente.

Eram excelentes notícias, pois o fórum seria recuperado sem que fosse perdido qualquer mensagem, apesar de que nem tudo fosse ficar da melhor forma. Esta intervenção iria fazer com que:

  • Como os títulos dos tópicos não eram recuperáveis através dos backups anteriores à migração para o nosso servidor, apenas poderíamos colocar um titulo sucessivo em cada tópico, exemplo “Tópico #1”, “Tópico #2”, “Tópico #3”, etc…;
  • Todos os tópicos do fórum iriam ficar colocados numa única secção/fórum;

Para além dos inconvenientes anteriores, todos os tópicos iriam ficar visíveis como sendo criados pelo utilizador fictício “unknow”, sem contagem do número de posts e com a data da ultima mensagem incorrecta.

No entanto esta informação poderia ser posteriormente corrigida utilizando as ferramentas disponíveis pelo core do IPB.

Desta forma apenas seria necessário a colaboração posterior dos colaboradores na alteração dos títulos dos tópicos e reorganização dos mesmos para as respectivas categorias/fóruns.

Fizemos alguns testes para confirmar se a solução estaria a funcionar correctamente numa primeira fase e verificamos que alguns dos utilizadores conseguiram participar nos tópicos em que estavam a ser executados os testes. Desta forma confirmamos a eficácia da solução.

Foi comunicada esta solução ao responsável pela comunidade Ricardo Miguel e ficamos a aguardar a sua confirmação para que pudesse ser colocada em prática esta solução.

Após termos recebido a confirmação do Ricardo para avançar com a implementação desta solução, desenvolvemos um pequeno script em PHP.

Este script demorou apenas alguns minutos a ser concluído e tinha muitas poucas linhas de código, fazendo apenas a verificação na base de dados de tópicos com mensagens associadas aos mesmos e recriando aqueles que tivessem posts associados ao seu id.

O código do script pode ser verificado abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

mysql_connect("localhost", "user_userbd", "password") or die(mysql_error());
echo "Connected to MySQL<br />";
mysql_select_db("user_bd") or die(mysql_error());
echo "Connected to Database<br />";

for($topico=1; $topico<=28000; $topico++) {

$sql = "SELECT * FROM `ibf_posts` WHERE `topic_id` = $topico";

$sql = mysql_query($sql);
if(mysql_num_rows($sql)==0){
echo "<br />Tópico $topico - Não existe<br />";

$total = $total+1;
}
else {
echo "<br />Tópico $topico - Inserido<br />";

$sql2 = "INSERT INTO `ibf_topics` (`tid`, `title`, `description`, `state`, `posts`, `starter_id`, `start_date`, `last_poster_id`, `last_post`, `icon_id`, `starter_name`, `last_poster_name`, `poll_state`, `last_vote`, `views`, `forum_id`, `approved`, `author_mode`, `pinned`, `moved_to`, `total_votes`, `topic_hasattach`, `topic_firstpost`, `topic_queuedposts`, `topic_open_time`, `topic_close_time`, `topic_rating_total`, `topic_rating_hits`) VALUES ($topico, 'Titulo $topico', NULL, 'open', '0', '1', '1300814482', '1', '0', '0', 'unknow', 'unknow', '0', '0', '0', '3', '1', '1', '0', NULL, '0', '0', '0', '0', '0', '0', '0', '0');";

echo $sql2;

$sql2 = mysql_query($sql2) or die(mysql_error());
}
}
echo $total;
?>

Para evitar problemas causados pela intervenção dos utilizadores durante esta manutenção, activamos a protecção da pasta do fórum por password, sendo n ecessário a autenticação para entrar no mesmo.

Posteriormente executamos o script desenvolvido e finalmente todos os tópicos e posts estavam acessiveis sem que fosse devolvido qualquer erro a nível de SQL.

Executamos o conjunto de scripts de sincronização e re-contagem do IPB para corrigir algumas situações do nome do criador dos tópicos e das datas, tendo ficado tudo a funcional.

Após ter sido terminada esta manutenção e confirmado que os posts estavam acessíveis, tendo sido a recuperação da comunidade concluída, efectuamos a transferência da base de dados para um servidor de testes onde foi feita a verificação e optimização de todas as tabelas da base de dados, tendo esta posteriormente sido transferida novamente para o servidor em produção.

Neste momento, e devido ao grande espírito de colaboração existente por parte da equipa do Contra Ataque, já é possível verificar que o título e a categoria de bastantes tópicos foram restaurados correctamente.

A comunidade encontra-se agora alojada num dos nossos servidores, com backups via R1soft com uma frequência de cópias de segurança bastante intensa.

R1soft

Esperamos que todos aqueles que estão a ler este artigo possam reter desta história algumas lições, sendo uma delas a necessidade de efectuar backups constantemente para além daqueles gerados pela empresa de alojamento e também prevenir a consistência dos dados fazendo uma monitorização activa do conteúdo dos backups, pois como se pôde verificar neste caso, apesar de existirem cópias de segurança, estas estavam corrompidas e incompletas.

A equipa WebTuga orgulha-se de ter conseguido com os seus conhecimentos técnicos recuperar esta comunidade sem que fosse perdidas informações juntas da origem da participação de uma comunidade tão grande ao longo de cerca de 5 anos, tendo noção de que outra empresa não faria o mesmo pelo seu próprio cliente e de que este poderia ter sido o fim desta comunidade.

Por esta razão, agradecemos a todos aqueles que confiam na nossa eficiência e profissionalismo, com a garantia de que iremos sempre lutar pela satisfação dos nossos clientes e colaboradores e nunca o iremos deixar mal.

Para concluir felicitamos o Ricardo Miguel e a comunidade Contra Ataque pelo excelente trabalho em conjunto que está a ser efectuado, deixando desde aqui o nosso apoio da nossa equipa. Graças a eles teremos também uma história para contar aos nossos netos, sendo aquele o dia em que recuperamos uma comunidade com 5 anos e mais de um milhão de posts.

  • Um dia normal de um SysAdmin… 🙁

  • Pedro Peralta

    Como membro da comunidade Contra-Ataque, realço a invulgar e espectacular envolvência e dedicação que a WebTuga deu a este projecto. Esta é uma comunidade importante para muita gente, criada com anos de esforço e dedicação. E devido ao vosso excelente trabalho, muito acima do que se iria esperar de uma outra empresa de alojamento (e assim vocês se destacam, fazem a diferença, mostram que são melhores), tudo se recuperou e tudo voltou à normalidade.

    Um muito obrigado pela vossa competência e trabalho. 😉

  • Filipe Silva

    Só me resta felicita-los pelo excelente trabalho realizado e agradecer pela disponibilidade que tiveram para com o forum e toda a sua dimensão e seguidores.

    Como membro do forum fica aqui a minha gratidão.

  • Darchil

    Já sou membro do Fórum Contra-Ataque há algum tempo, e só vos consigo fizer uma coisa: Obrigado.

    Perder os posts e tópicos seria muito frustrante, são 5 anos de história que ia “por água abaixo”.

    Por isso, muito obrigado por este excelente trabalho.

  • Cláudio Rocha

    Obrigado, simplesmente. Obrigado por tudo 😉

  • Excelente trabalho. Eu bem vi a trabalheira que deu, parabéns. Eu ainda me lembro desse fórum ter sido criado apesar de nunca ter participado, mas acho que o meu registo ainda por lá anda. 🙂

    Força!

  • hexagonix

    Mais um membro do CA a agradecer pelo trabalho feito 😉

    Thanks, honestly.

  • Não há muito mais a dizer sobre o excelente trabalho que a WebTuga realizou. Ficarei para sempre grato com o serviço de qualidade e profissional que foi prestado nesta situação que cada vez se adivinhava mais trágica.

    Um muito obrigado.

    @ João Silas, o teu registo ainda lá continua como um dos primeiros 100 membros do fórum. Não te deves lembrar de mim, mas chegámos a falar uns meses antes de ter criado o CA, quando eu me iniciei neste mundo. 🙂

  • Miguel

    Não podia deixar de dar também eu as felicitações pelo excelente trabalho desenvolvido e pela dedicação demonstrada que resultou na salvaguarda de 5 anos de história de um fórum no qual também participo há algum tempo.

    Fica aqui também o meu agradecimento pelo serviço prestado. 🙂

    @ João Silas: tal como o Ricardo, também não te deves lembrar de mim mas também te “e-conheço” xD cheguei a participar no teu antigo fórum, que conheci pelo Dudas. 😛