Conheça seu servidor


Um post do Jeff Atwood me chamou a atenção semana passada. Ele relata como teve dificuldades para encontrar um problema no StackOverflow beta. Eles encontravam logs de deadlocks durante o dia e no fim descobriram que o problema estava relacionado ao travamento de leitores feito pelo MS SQL Server (tradução livre):

Você pode anexar o profiler para pegar o evento de deadlock e ver qual o exato comando que o está causando. Eu fiz isso e achei sempre um mesmo comando SQL:

UPDATE [Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0

Se detectar um deadlock o SQL Server força um dos comandos envolvidos a dar erro – especificamente aquele que usa menos recursos. Os comandos envolvidos variavam, mas no nosso caso o comando que dava erro era sempre uma leitura inócua, assim:

SELECT *
FROM [Posts]
WHERE [ParentId] = @p0

Para resolver o problema foi preciso instruir o SQL Server a usar leituras sujas em cada uma das leituras onde havia perigo de travamento.

O que ficou me martelando a cabeça todos esses dias não é como pode um banco de dados moderno ainda ter travamento de leitores. E sim a lição que podemos tirar deste episódio. Independente do servidor e de suas limitações de arquitetura, o importante é você conhecê-lo bem e conhecer bem o ambiente da sua aplicação.

No caso do StackOverflow o Jeff descobriu que uma possível solução era a leitura suja. Se a sua aplicação tivesse transações longas as leituras sujas não seriam uma opção. Mas conhecendo bem sua aplicação ele sabia que não era esse o caso e que não teria maiores conseqüências se as usasse. Independente do que diriam os puristas de ACID. E confesso que eu mesmo torci o nariz assim que li “leitura suja”.

Graças a sua arquitetura multi-geração o Firebird não tem travamento de leitores. Então é natural que este problema pareça estranho para nós. Mas cada arquitetura tem seus prós e contras. Esta mesma arquitetura multi-geração se não for bem utilizada pode ser um problema. É o caso de transações que ficam abertas por muito tempo.

Tais transações levam a um acúmulo de versões de registros dentro do banco de dados. (Estas versões também podem ser chamadas de gerações. A arquitetura é multi-geração, lembra?) Quanto mais versões acumuladas, mais trabalho o Firebird tem que realizar para encontrar a versão correta de cada registro. Dado tempo suficiente o acúmulo de versões é tão grande que o servidor Firebird fica lento o suficiente para parecer travado. Esse tempo depende muito da carga do banco de dados e do hardware do servidor. Pode ser um mês, pode ser uma hora.

Eu vi isso acontecer em um bom número de ocasiões. Em algumas delas vi gerentes argumentarem durante horas que o MS SQL Server e o Oracle não têm esse problema. O fato é que eles têm outros detalhes de arquitetura que você deverá levar em conta na sua aplicação. Por exemplo, travamento de leitores. Simplesmente trocar de banco de dados, como alguns desses gerentes chegaram a sugerir, não é uma solução.

Se bem que o StackOverflow rodando em Firebird não seria má idéia. ;)

Faça um comentário