O que acontece se você não confirmar uma transação em um banco de dados (por exemplo, SQL Server)?

108

Suponha que eu tenha uma consulta:

begin tran
-- some other sql code

E então eu esqueço de confirmar ou reverter.

Se outro cliente tentar executar uma consulta, o que acontecerá?

Charbel
fonte

Respostas:

148

Contanto que você não COMMIT ou ROLLBACK uma transação, ela ainda está "executando" e potencialmente segurando bloqueios.

Se o seu cliente (aplicativo ou usuário) fechar a conexão com o banco de dados antes de confirmar, todas as transações ainda em execução serão revertidas e encerradas.

marc_s
fonte
1
mmm, ok, descobri que isso estava criando algum tipo de bloqueio. Eu não tinha certeza de que fechar a conexão realmente me tiraria desse estado. o problema era que eu estava recebendo um erro quando tento fazer o commit. agora fechei a conexão e deu tudo certo.
Charbel
12
Observação lateral: se estiver usando o Management Studio, fechar a janela de consulta fechará a conexão
Joe Phillips
3
@BradleyDotNET: sim, definitivamente
marc_s
2
Lembre-se de que o SQL Server Management Studio confirma automaticamente se você fechar a janela / conexão de consulta, por padrão.
Nuno
1
Observe que quando o cliente fecha a conexão enquanto uma transação está ativa, nem sempre é revertida - isso depende do cliente e do banco de dados. Por exemplo, quando um aplicativo Java fecha uma conexão com um banco de dados Oracle, todas as conexões abertas são confirmadas automaticamente.
AviD
38

Você pode tentar fazer isso sozinho, o que deve ajudá-lo a ter uma ideia de como isso funciona.

Abra duas janelas (abas) no management studio, cada uma delas terá sua própria conexão ao sql.

Agora você pode iniciar uma transação em uma janela, fazer algumas coisas como inserir / atualizar / excluir, mas ainda não confirmar. em seguida, na outra janela, você pode ver como o banco de dados se parece de fora da transação. Dependendo do nível de isolamento, a tabela pode ser bloqueada até que a primeira janela seja confirmada ou você pode (não) ver o que a outra transação fez até agora, etc.

Brinque com os diferentes níveis de isolamento e nenhuma dica de bloqueio para ver como eles afetam os resultados.

Veja também o que acontece quando você lança um erro na transação.

É muito importante entender como tudo isso funciona ou você ficará perplexo com o que o sql faz, muitas vezes.

Diverta-se! GJ.

gjvdkamp
fonte
ok, mas a transação será gravada no log pelo menos antes de emitir o commit? Por exemplo, digamos que eu queira iniciar uma transação, executar um comando de inserção e "fazer outra coisa" antes de executar o commit. meu comando de inserção será gravado no log? dessa forma, se o servidor travar antes de executar o commit ... ele pode voltar para onde estava e eu posso apenas emitir o commit mais tarde (sempre que terminar de fazer "outra coisa").
user1870400
16

As transações devem ser executadas completamente ou nunca. A única maneira de completar uma transação é confirmar, qualquer outra forma resultará em uma reversão.

Portanto, se você iniciar e não confirmar, ele será revertido no fechamento da conexão (pois a transação foi interrompida sem ser marcada como concluída).

Piskvor saiu do prédio
fonte
É assim que deveria ser, mas nem sempre é o caso.
FalcoGer
... como o MyISAM do mySQL, que não suporta transações, com certeza.
Piskvor saiu do prédio em
3

depende do nível de isolamento da transação incomming.

Explicado o isolamento da transação Sql

Xhalent
fonte
6
O comportamento das transações não depende do nível de isolamento. A quantidade de bloqueios que eles podem causar sim.
marc_s
Tenho certeza de que os dados que podem ser lidos por uma conexão dependem definitivamente do nível de isolamento. Se você tiver o isolamento definido como READ UNCOMMITTED, poderá ler os dados ainda não confirmados e podem, de fato, ser revertidos em algum ponto da trilha, mas isso garante que não haja travamento. Se você tiver READ COMMITTED como seu nível de isolamento, não poderá ler linhas não confirmadas - o segundo cliente irá travar a menos que você use SNAPSHOT.
Xhalent
2

Quando você abre uma transação, nada é bloqueado por si só. Mas se você executar algumas consultas dentro dessa transação, dependendo do nível de isolamento, algumas linhas, tabelas ou páginas serão bloqueadas e afetarão outras consultas que tentam acessá-las de outras transações.

trevo vermelho
fonte
1

Exemplo de transação

começar o tran tt

Suas declarações sql

se ocorreu um erro rollback tran tt else commit tran tt

Enquanto você não executou o commit tran tt, os dados não serão alterados

user3386471
fonte
1
Observe que nomear transações não é apenas desnecessário no MS SQL, mas pode dar uma falsa sensação de controle. BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Ynão funciona, por exemplo. Consulte stackoverflow.com/questions/1273376/…
0

Além dos possíveis problemas de bloqueio que você pode causar, você também descobrirá que seus logs de transações começam a crescer, pois não podem ser truncados além do LSN mínimo para uma transação ativa e se você estiver usando o isolamento de instantâneo, seu armazenamento de versão em tempdb aumentará para razões semelhantes.

Você pode usar dbcc opentranpara ver os detalhes da transação aberta mais antiga.

Martin Smith
fonte
0

Qualquer transação não realizada deixará o servidor bloqueado e outras consultas não serão executadas no servidor. Você precisa reverter a transação ou confirmá-la. O fechamento do SSMS também encerrará a transação, o que permitirá que outras consultas sejam executadas.

Josh Moorish
fonte
-4

O comportamento não está definido, então você deve definir explicitamente um commit ou rollback:

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

"Se o modo auto-commit estiver desabilitado e você fechar a conexão sem explicitamente confirmar ou reverter suas últimas mudanças, então uma operação COMMIT implícita é executada."

Hsqldb faz uma reversão

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

resultado é

2011-11-14 14: 20: 22.519 INFO principal [SqlAutoCommitExample: 55] [AutoCommit ativado = falso] 2011-11-14 14: 20: 22.546 INFO principal [SqlAutoCommitExample: 65] [Encontrou 0 # usuários no banco de dados]

Bernd Schatz
fonte
2
Isso pode ser verdade para a Oracle (não tenho ideia), mas o questionador está perguntando sobre o MS-SQL
PaulG
A primeira citação se aplica ao driver JDBC, não ao servidor.
Djechlin,