Data

14 mai, 2015

O custo de uma transação que tem apenas applocks no SQL Server

Publicidade

Recentemente acompanhei uma discussão sobre os méritos do uso do SQL Server como um gerenciador de bloqueio de aplicativos. O aplicativo iria iniciar uma transação e adquirir bloqueios de aplicativos, usando sp_getapplock. Nenhum dado real seria consultado ou modificado nessa transação. A questão é se o uso do SQL Server como tal, basicamente como um gerenciador de bloqueio de aplicativos, pode levar a problemas no SQL Server.

Bloqueios são relativamente baratos para o servidor. O motor pode adquirir, conceder e liberar milhões deles por segundo. Um bloqueio comum pode custar uma pequena quantidade de memória, mas o bloqueio global é uma parte tão importante e crítica de uma operação SQL Server que tudo relacionado aos bloqueios será altamente otimizado. O sp_getapplock é basicamente apenas um shell em torno dos recursos do gerenciador de bloqueio e, como tal, torna-se um “free ride”. Altamente otimizado, os bloqueios são eficientes e rápidos. No entanto, esse não é o único custo associado a bloqueios de aplicativos. Transações que possuem no escopo um bloqueio de aplicativo também devem funcionar pelas regras de reversão de transação e recuperação, e uma regra é que os bloqueios exclusivos adquiridos por transações devem ser registrados, uma vez que devem ser readquiridos durante a recuperação dos dados. Bloqueios de aplicativos não são diferentes, e isso é fácil de testar:

create database test;
go

alter database test set recovery  full;
go

backup database test to disk = 'nul:';
go

use test;
go

begin transaction
exec sp_getapplock 'foo', 'Exclusive', 'Transaction'
select * from sys.fn_dblog(null, null);

 

00000021:0000005b:0001	LOP_BEGIN_XACT   ... user_transaction
00000021:0000005b:0002	LOP_LOCK_XACT    ... ACQUIRE_LOCK_X APPLICATION: 5:0:[fo]:(ea53e177)

Claro que foram feitos registros de log suficientes durante a execução de nossa transação, desde que ela adquiriu um bloqueio de aplicativo exclusivo. Isso significa que se o aplicativo está usando o SQL Server como um gerenciador de bloqueio e está mantendo bloqueios de longa vida (por exemplo, ao fazer uma solicitação HTTP), ele também está gerando logs, impedindo o truncamento. Outro efeito colateral é registrar o tráfego, se o aplicativo está solicitando lotes de bloqueios de apps que podem resultar em notável rendimento na gravação do log.

Mencionei que a obrigação de registrar os bloqueios exclusivos adquiridos em uma transação é necessária. Uma vez que o tempdb nunca é recuperado, ele tem um modelo de exploração dos dados mais maleável. Especificamente, ele não é obrigado a registrar bloqueios exclusivos adquiridos por transações. Então, se você repetir a mesma experiência anterior, mas no tempdb, verá que nenhum registro de log é gerado:

use tempdb;
go

begin transaction
exec sp_getapplock 'foo', 'Exclusive', 'Transaction'
select * from sys.fn_dblog(null, null);

Verifique que o contexto atual está definido para tempdb ao chamar sp_getapplock, então, você obtém um gerenciador de bloqueio de alto desempenho para seu aplicativo, com pouca sobrecarga para o motor do SQL Server. Esta é, na verdade, uma forma trivial de conseguir o mesmo resultado na prática:

use test
go

begin transaction
exec tempdb..sp_getapplock 'foo', 'Exclusive', 'Transaction'
select * from sys.fn_dblog(null, null)

Simplesmente utilizando o nome de 3 partes no tempdb..sp_getapplock, eu efetivamente suprimi o registro do bloqueio adquirido pelo aplicativo! É claro que é necessário ter cautela: por favor, certifique-se de que você está de acordo com bloqueios de aplicativos não sendo registrados. O importante a considerar é como irá se comportar o aplicativo ao fazer uma recuperação de dados online. Se bloqueios de aplicativos não forem registrados, isso pode gerar um bloqueio aos dados que foram protegidos por um bloqueio de aplicativo que está sendo lido. Na prática, isso raramente é um caso para preocupação, mas você tem que considerar e reconhecer os problemas que isso pode trazer.

***

Remus Rusanu faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://rusanu.com/2015/03/06/the-cost-of-a-transactions-that-has-only-applocks/