O TOTVS | DBAccess adota, para a maioria dos bancos, o nível de isolamento READ UNCOMMITTED por não serializar as operações e a leitura dos registros. Com isto, pode haver leitura suja nas operações de leituras da base de dados, isto é, a transação corrente pode obter dados das transações ainda não comitadas por outras conexões.
O nível de isolamento adotado garante que as leituras realizadas no banco de dados pela aplicação não realizem bloqueio de registros e por consequência não serializem a aplicação, mantendo a previsibilidade do desempenho. Porém alguns cuidados devem ser observados para garantir a integridade dos dados.
Quando se adota leituras sujas deve-se prevenir que em atualizações, os dados sejam bloqueados antes de serem atualizados ou lidos com este fim. A transação T2 tem uma linha alterada, mas ainda não finalizada. A transação T1 lê os dados atualizados e os atualiza com base nos dados lidos. A transação T1 fecha a transação e a transação T2 realiza um Roll Back dos dados. A partir deste momento os dados não estão mais íntegros.
Para evitar esta situação, o desenvolvedor deve indicar a aplicação o momento do bloqueio, isto é feito utilizando a função RecLock, conforme demonstrado abaixo:
// ReadSample.prw Begin Transaction RecLock("SB2") nQtd := SB2->B2_QATU If nQtd + nSoma <= 0 SB2->B2_QATU := 0 Else SB2->B2_QATU := nQtd - nSoma EndIf MsUnlock() End Transaction
A função RecLock informa para o Framework da aplicação realizar o bloqueio do registro posicionado. O Framework realiza o bloqueio e atualiza a leitura do registro corrente da tabela. As demais transações do sistema continuam lendo o registro bloqueado, porém se tentarem bloquear o registro deverá aguardar a transação anterior liberá-lo, o que somente pode ser realizado ao termino da transação.
Outra prevenção a ser considerada nas leituras sujas são as atualizações parciais, decorrentes do relacionamento de dependência direta das tabelas. Para um formulário do tipo Master/Detail (cabeçalho e Item), a transação de inserção deste formulário permite que o registro da tabela Master exista sem os registros ou com uma quantidade parcial dos registros da tabela Detail, haja vista que é a única forma de garantir a dependência da chave estrangeira. Se uma rotina de atualização realizar o bloqueio apenas nos registros Detail não há como garantir que todos os registros sejam considerados. Portanto é necessário bloquear o registro Master, antes do inicio do bloqueio dos registros Detail em qualquer atualização dos registros Detail. Ao bloquear o registro Master, garante-se que nenhum registro da tabela Detail, vinculado ao Master, esteja em atualização ou inserção. É fato que dependendo da rotina desenvolvida, é obrigatório iniciar a leitura pela tabela Detail e não pela Master. Nestas situações deve-se garantir que, antes de qualquer atualização do registro Detail, o registro Master seja bloqueado antes do registro Detail.
No exemplo são mencionadas apenas duas tabelas, porém independentemente da quantidade de tabelas envolvidas no formulário, o registro Master deve ser bloqueado.
Por último, existe a prevenção do momento do COMMIT. A arquitetura do Server Application da linha Microsiga Protheus faz com que o momento do COMMIT seja automático, conforme a lógica do programa, assim como pode utilizar mais de um canal de comunicação com o SGBD para leitura. Se o Server Application utiliza mais de um canal para leitura, é possível inferir que os demais canais de leitura somente “visualizarão” os registros, cujos dados foram comitados. Para prevenir qualquer tipo problema na leitura através de querys, é necessário forçar o COMMIT dos dados, conforme demonstrado abaixo.
// CommitSample.prw SPED050->(DbCommit()) BeginSQL Alias cAlias SELECT R_E_C_N_O_ FROM SPED050 WHERE ID_ENT = %Exp:cIdEnt% AND (STATUS = 1 OR STATUS = 2 OR STATUSDPEC = 1) AND STATUSDPEC <> 5 AND %NOTDEL% EndSQL
O nível de isolamento READ UNCOMMITTED é o mais aconselhável para aplicação do tipo de aplicação OLTP (On Line Transaction Process), porém cabe ao desenvolvedor o controle do formato de leitura e o bloqueio do registro para atualização.