TRANSAÇÕES Lílian Simão Oliveira Fonte: Material de referência do SQL Server 2008 R2, disponível em: http://msdn.microsoft.com/ptbr/library/bb418439%28v=SQL.10%29.aspx Transações Uma transação é uma seqüência de operações executadas como uma única unidade lógica de trabalho. Uma unidade lógica de trabalho deve mostrar quatro propriedades, designadas pelas iniciais ACID (atomicidade, consistência, isolamento e durabilidade), para que seja qualificada como uma transação. Transações: Atomicidade Uma transação deve ser uma unidade atômica de trabalho; ou todas as suas modificações de dados são executadas ou nenhuma delas é executada. Transações: Consistência Quando concluída, uma transação deve deixar todos os dados em um estado consistente. Em um banco de dados relacional, todas as regras devem ser aplicadas às modificações da transação para manter toda a integridade dos dados. Todas as estruturas de dados internas, tais como índices em árvore B ou listas duplamente vinculadas, devem estar corretas ao término da transação. Transações: Isolamento Modificações feitas por transações simultâneas devem ser isoladas das modificações feitas por qualquer outra transação simultânea. Uma transação reconhece os dados no estado em que estavam antes de outra transação simultânea tê-los modificado ou reconhece os dados depois que a segunda transação tiver sido concluída, mas não reconhece um estado intermediário. Isso é chamado serializabilidade porque resulta na capacidade de recarregar os dados iniciais e reexecutar uma série de transações de modo que os dados obtidos estejam no mesmo estado em que estavam depois que as transações originais foram executadas. Transações: Durabilidade Depois que uma transação tiver sido concluída, seus efeitos ficam permanentemente no sistema. As modificações persistem até mesmo no caso de uma queda do sistema. Transações – o que é responsabilidade do programador? Iniciar e terminar transações em pontos que imponham a consistência lógica dos dados. Definir a seqüência de modificações de dados que deixem os dados em um estado consistente em relação às regras comerciais da organização. E inclui essas instruções de modificação em uma única transação de modo que o Mecanismo de banco de dados do SQL Server possa aplicar a integridade física da transação. Transações – o que é responsabilidade do BD? Oferecer mecanismos que assegurem a integridade física de cada transação. O Mecanismo de Banco de Dados oferece: Recursos de bloqueio que preservam o isolamento da transação. Recursos de log que garantem a durabilidade da transação. Mesmo se o hardware do servidor, o sistema operacional ou a instância do Mecanismo de Banco de Dados falharem, a instância usa os logs da transação ao reinicializar para reverter automaticamente qualquer transação incompleta até o ponto da falha do sistema. Recursos de administração de transação que impõem a atomicidade e a consistência da transação. Depois que uma transação tiver sido iniciada, ela deve ser concluída com êxito ou a instância do Mecanismo de Banco de Dados desfará todas as modificações de dados feitas desde que a transação foi iniciada. Controlando transações Os aplicativos controlam transações principalmente ao especificar quando uma transação começa e termina. Isso pode ser especificado pelo uso de instruções Transact-SQL ou funções de interface de programação de aplicativo (API) de banco de dados. O sistema também deve ser capaz de processar corretamente os erros que encerram uma transação antes de sua conclusão. Por padrão, as transações são gerenciadas no nível de conexão. Quando uma transação é iniciada em uma conexão, todas as instruções TransactSQL executadas nessa conexão fazem parte da transação até a conclusão da transação. Porém, em uma sessão de vários conjuntos de resultados ativos (MARS1), uma transação Transact-SQL explícita ou implícita se torna uma transação no escopo do lote gerenciada no nível do lote. Quando o lote for concluído, se a transação no escopo do lote não for confirmada ou revertida, ela será revertida automaticamente pelo SQL Server. 1 – Mais informações sobre MARS: http://msdn.microsoft.com/pt-br/library/ms131686.aspx Iniciando transações Ao usar funções de API e instruções Transact-SQL, você pode iniciar transações em uma instância do Mecanismo de banco de dados do SQL Server como transações explícitas, autoconfirmadas ou implícitas. Em uma sessão de MARS, as transações explícitas e implícitas do Transact-SQL se tornam transações no escopo do lote. Iniciando transações Transações explícitas Uma transação explícita é aquela para a qual você define o início e término da transação explicitamente. Inicie uma transação explicitamente por uma função de API ou emitindo a instrução Transact-SQL BEGIN TRANSACTION. Os aplicativos DB-Library e scripts Transact-SQL usam as instruções BEGIN TRANSACTION, COMMIT TRANSACTION, COMMIT WORK, ROLLBACK TRANSACTION ou ROLLBACK WORK Transact-SQL para definir transações explícitas. Iniciando transações Transações de confirmação automática O modo de confirmação automática é o modo padrão de gerenciamento de transações do Mecanismo de banco de dados do SQL Server. Toda instrução Transact-SQL é confirmada ou revertida quando concluída. Se uma instrução for concluída com sucesso, será confirmada; se encontrar qualquer erro, será revertida. Uma conexão para uma instância do Mecanismo de Banco de Dados opera em modo de confirmação automática sempre que esse modo padrão não for substituído por transações explícitas ou implícitas. O modo padrão do Mecanismo de Banco de Dados. Cada instrução Transact-SQL individual é confirmada na conclusão. Você não precisa especificar nenhuma instrução para controlar transações. Iniciando transações Transações implícitas Quando uma conexão operar em modo de transação implícita, a instância do Mecanismo de banco de dados do SQL Server iniciará automaticamente uma nova transação depois que a transação atual for confirmada ou revertida. Você não faz nada para determinar o início de uma transação; apenas confirma ou reverte cada uma das transações. O modo de transação implícita gera uma cadeia contínua de transações. Defina o modo de transação implícito como ativado por uma função de API ou pela instrução Transact-SQL SET IMPLICIT_TRANSACTIONS ON. A próxima instrução inicia uma nova transação automaticamente. Quando essa transação é concluída, a próxima instrução Transact-SQL inicia uma nova transação. Iniciando transações Transações no escopo de lote Aplicável apenas a vários conjuntos de resultados ativos (MARS), uma transação Transact-SQL explícita ou implícita iniciada em uma sessão MARS se torna uma transação no escopo do lote. Uma transação no escopo do lote não confirmada ou revertida quando um lote é concluído é revertida automaticamente pelo SQL Server. Iniciando transações Os modos de transação são gerenciados no nível de conexão. Se uma conexão for alterada de um modo de transação para outro, isso não terá nenhum efeito nos modos de transação de qualquer outra conexão. Finalizando uma transação Você pode finalizar transações com uma instrução COMMIT ou ROLLBACK ou por uma função de API. COMMIT Se uma transação for concluída com êxito, confirme-a. Uma instrução COMMIT garante que todas as modificações na transação fazem parte permanente do banco de dados. Um COMMIT também libera recursos, como bloqueios, usados pela transação. ROLLBACK Se ocorrer um erro em uma transação ou se o usuário decidir cancelá-la, reverta a transação. Uma instrução ROLLBACK desfaz todas as modificações feitas na transação retornando os dados ao estado anterior ao início da transação. Um ROLLBACK também libera recursos usados pela transação. Especificando os limites de uma transação Você pode identificar quando as transações Mecanismo de Banco de Dados são iniciadas e finalizadas com instruções Transact-SQL ou funções e métodos de API. Instruções Transact-SQL Use as instruções BEGIN TRANSACTION, COMMIT TRANSACTION, COMMIT WORK, ROLLBACK TRANSACTION, ROLLBACK WORK e SET IMPLICIT_TRANSACTIONS para delinear transações. Elas são usadas principalmente em aplicativos DB-Library e em scripts Transact-SQL, como os scripts executados usando o utilitário de prompt de comando osql. Especificando os limites de uma transação Funções e métodos de API As APIs de banco de dados como ODBC, OLE DB, ADO e o namespace do SQLClient do .NET Framework contêm funções ou métodos usados para delinear transações. Elas são os mecanismos principais usados para controlar transações em um aplicativo Mecanismo de Banco de Dados. Cada transação deve ser gerenciada por apenas um desses métodos. Usar ambos os métodos na mesma transação pode levar a resultados indefinidos. Por exemplo, você não deve iniciar uma transação usando as funções de API ODBC e, depois, usar a instrução COMMIT do Transact-SQL para concluir a transação. Isso não notificaria o driver ODBC SQL Server de que a transação está confirmada. Nesse caso, use a função SQLEndTran de ODBC para finalizar a transação. Erros durante o processo de transação Se um erro impedir a conclusão bem-sucedida de uma transação, o SQL Server reverterá automaticamente a transação e liberará todos os recursos usados por ela. Se a conexão de rede do cliente com uma instância do Mecanismo de Banco de Dados for interrompida, quaisquer transações pendentes para a conexão serão revertidas quando a rede notificar a instância sobre a interrupção. Se o aplicativo cliente falhar ou se o computador cliente for desligado ou reiniciado, isso também interromperá a conexão e a instância do Mecanismo de Banco de Dados reverterá quaisquer conexões pendentes quando a rede notificar a interrupção. Se o cliente fizer logoff do aplicativo, quaisquer transações pendentes serão revertidas. Erros durante o processo de transação Se ocorrer um erro de instrução de tempo de execução (como uma violação de restrição) em um lote, o comportamento padrão no Mecanismo de Banco de Dados será reverter somente a instrução que gerou o erro. Você pode alterar esse comportamento usando a instrução SET XACT_ABORT. Depois que SET XACT_ABORT ON for executada, qualquer erro de instrução em tempo de execução fará com que a transação atual seja revertida. Os erros de compilação, como erros de sintaxe, não são afetados por SET XACT_ABORT. Quando ocorrerem erros, a ação corretiva (COMMIT ou ROLLBACK) deverá ser incluída em um código de aplicativo. Uma ferramenta eficiente para processar erros, inclusive aqueles em transações, é a construção TRY...CATCH no Transact-SQL. Transações Distribuidas Transações distribuídas abrangem dois ou mais servidores conhecidos como gerenciadores de recursos. O gerenciamento da transação deve ser coordenado entre os gerenciadores de recursos por um componente de servidor chamado de gerenciador de transações. Cada instância do Mecanismo de banco de dados do SQL Server pode operar como um gerenciador de recursos em transações distribuídas coordenadas por gerenciadores de transações, como o MS DTC (Coordenador de Transações Distribuídas da Microsoft), ou outros gerenciadores de transações que dão suporte à especificação XA do Open Group para processamento de transações distribuídas. Transações Distribuidas Uma transação em uma instância única do Mecanismo de Banco de Dados que abrange dois ou mais bancos de dados é, de fato, uma transação distribuída. A instância gerencia a transação distribuída internamente. Para o usuário, ela opera como uma transação local. Transações Distribuidas No aplicativo, uma transação distribuída é gerenciada da mesma forma como uma transação local. No final da transação, o aplicativo solicita que a transação seja confirmada ou revertida. Uma confirmação distribuída deve ser gerenciada de forma diferenciada pelo gerenciador de transações para minimizar o risco de que uma falha de rede possa resultar em alguns gerenciadores de recurso que confirmam com êxito enquanto outros revertem a transação. Isso é obtido pelo gerenciamento do processo de confirmação em duas fases (a fase de preparação e a fase de confirmação), o que é conhecido como um protocolo 2PC. Transação Distribuida Fase de Preparo Quando o gerenciador de transações recebe uma solicitação de confirmação, ele envia um comando de preparação a todos os gerenciadores de recursos envolvidos na transação. Cada gerenciador executa todas as ações necessárias para tornar a transação durável, e todos os buffers que mantêm imagens de log da transação são liberados no disco. À medida que cada gerenciador de recursos conclui a fase de preparação, ele retorna informações de êxito ou de falha ao gerenciador de transações. Transação Distribuida Fase de Confirmação Se o gerenciador de transações receber preparos bemsucedidos de todos os gerenciadores de recursos, ele enviará comandos de confirmação a cada gerenciador de recursos. Em seguida, os gerenciadores de recursos podem concluir a confirmação. Se todos os gerenciadores de recursos relatarem uma confirmação bem-sucedida, o gerenciador de transações enviará uma notificação de êxito ao aplicativo. Se um gerenciador de recursos informar uma falha na preparação, o gerenciador de transações enviará um comando de reversão a cada gerenciador de recursos e indicará a falha da confirmação ao aplicativo. Tópicos Avançados - Transações O gerenciamento incorreto de transações leva em geral a problemas de contenção e de desempenho em sistemas com muitos usuários. Conforme aumenta o número de usuários em um sistema, é importante ter aplicativos que utilizem as transações de maneira eficaz. O Mecanismo de banco de dados do SQL Server também dá suporte a aninhamento de transações, pontos de salvamento de transação e transações associadas, que oferecem aos programadores outras opções para gravar transações eficazes. Tópicos Avançados - Transações Aninhamento de transações Explica como aninhar transações em procedimentos armazenados que podem ser chamados de sessões que podem ou não ter uma transação ativa. http://msdn.microsoft.com/pt-br/library/ms189336.aspx Tópicos Avançados - Transações Ponto de salvamento de uma transação Os pontos de salvamento oferecem um mecanismo de reversão de partes de uma transação. http://msdn.microsoft.com/pt-br/library/ms178157.aspx Tópicos Avançados - Transações Usando sessões associadas Duas sessões podem ser associadas, compartilhando uma transação comum e um conjunto de bloqueios. http://msdn.microsoft.com/pt-br/library/ms177480.aspx Tópicos Avançados - Transações Ajustando o nível de isolamento da transação A escolha de um nível de isolamento define como a sessão atual é isolada de atualizações executadas por outras sessões. http://msdn.microsoft.com/pt-br/library/ms189542.aspx Tópicos Avançados - Transações Reversões e confirmações em procedimentos armazenadas e disparadores Discute os comportamentos associados à reversão de uma transação de um procedimento armazenado ou gatilho. http://msdn.microsoft.com/pt-br/library/ms187844.aspx Tópicos Avançados - Transações Instruções Transact-SQL permitidas em transações Determinadas instruções não podem ser executadas em uma transação ativa. http://msdn.microsoft.com/pt-br/library/ms191544.aspx Codificando Transações Eficientes É importante manter as transações tão curtas quanto possível. Quando uma transação é iniciada, um DBMS (Sistema de administração de banco de dados), deve manter muitos recursos, até o término da transação, para proteger as propriedades (ACID) de atomicidade, consistência, isolamento e durabilidade da transação. Se os dados forem modificados, as linhas modificadas devem ser protegidas com bloqueios exclusivos que evitem a leitura das linhas por qualquer outra transação, e os bloqueios exclusivos devem ser mantidos até que a transação seja confirmada ou revertida. Dependendo das configurações de nível de isolamento da transação, as instruções SELECT podem obter bloqueios que devem ser mantidos até que a transação esteja confirmada ou revertida. Especialmente em sistemas com muitos usuários, as transações devem ser mantidas tão curtas quanto possível para reduzir a contenção de bloqueios de recursos em conexões simultâneas. Transações longas e ineficazes podem não causar problemas com um número pequeno de usuários, mas são intoleráveis em um sistema com milhares de usuários. http://msdn.microsoft.com/pt-br/library/ms187484.aspx Codificando Transações Eficientes: Diretrizes Não solicite entradas de usuários durante a transação. Obtenha todas as entradas necessárias da parte dos usuários antes do início de uma transação. Sendo necessária uma entrada adicional de usuário durante uma transação, reverta a transação atual e reinicie a transação depois que a entrada do usuário for fornecida. Mesmo que os usuários respondam imediatamente, a reação humana é muito mais lenta que a velocidade do computador. Todos os recursos mantidos pela transação são retidos por um tempo extremamente longo, criando potencial para causar problemas de bloqueio. Se os usuários não responderem, a transação permanecerá ativa, bloqueando recursos críticos até que eles respondam, o que pode não acontecer por vários minutos ou até mesmo horas. Não abra uma transação enquanto estiver navegando pelos dados, se possível. As transações não devem ser iniciadas até que toda a análise preliminar de dados tenha terminado. Mantenha a transação tão curta quanto possível. Depois de saber quais são as modificações que precisam ser feitas, inicie uma transação, execute as instruções de modificação e, em seguida, confirme ou reverta imediatamente. Só abra a transação quando for necessário. Codificando Transações Eficientes: Diretrizes Para reduzir o bloqueio, considere usar um nível de isolamento de linha baseado em versão para consultas somente leitura. Utilize bem os níveis de isolamento de transação inferiores. Muitos aplicativos podem ser prontamente codificados para usar um nível de isolamento de transação confirmada por leitura. Nem todas as transações requerem nível de isolamento de transação serializável. Utilize bem as opções inferiores de simultaneidade de cursor, como opções de simultaneidade otimista. Em um sistema com pouca probabilidade de atualizações simultâneas, a sobrecarga de lidar com um erro ocasional quando "alguém altera seus dados depois que você os leu" pode ser muito inferior à sobrecarga de sempre bloquear linhas à medida que são lidas. Acesse a menor quantidade de dados possível enquanto estiver em uma transação. Isso reduz o número de linhas bloqueadas, reduzindo, portanto, a contenção entre transações. Evitando problemas de simultaneidade Para impedir problemas de simultaneidade e de recurso, gerencie cuidadosamente as transações implícitas. Ao usar transações implícitas, a próxima instrução do Transact-SQL após COMMIT ou ROLLBACK iniciará automaticamente uma nova transação. Isso pode fazer com que uma nova transação seja aberta enquanto o aplicativo navega pelos dados, ou até mesmo quando solicita entradas da parte do usuário. Depois de completar a última transação necessária à proteção contra modificações de dados, desative as transações implícitas até que a transação seja novamente necessária para proteger as modificações de dados. Esse processo deixa o Mecanismo de banco de dados do SQL Server usar o modo autocommit enquanto o aplicativo navega pelos dados e obtém entradas do usuário.