web-dev-qa-db-fra.com

Impossible de poursuivre l'exécution car la session est en état d'arrêt. lors de la création d'un index clusterisé

J'obtiens l'erreur suivante en essayant de créer un index clusterisé

La déclaration est terminée.
Msg 596, niveau 21, état 1, ligne 0
Impossible de poursuivre l'exécution car la session est en état d'arrêt.

Msg 0, niveau 20, état 0, ligne 0
Une erreur grave s'est produite sur la commande actuelle. Le cas échéant, les résultats doivent être ignorés.

L'index est:

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT

BEGIN TRANSACTION
GO

CREATE CLUSTERED INDEX IX_CO_DES_INPUT 
ON dbo.CO_DES_INPUT(DESIGN_ID, PRODUCT_INPUT_NUM, INPUT_NAME)
          WITH(STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
               ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

ALTER TABLE dbo.CO_DES_INPUT 
  SET (LOCK_ESCALATION = TABLE)
GO
COMMIT

J'utilise Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64) Standard Edition (64 bits) sur Windows NT 6.3 (Build 9600:)

J'ai couru

DBCC CheckDB ('concept-test') WITH NO_INFOMSGS, ALL_ERRORMSGS  

et il n'a trouvé aucun problème

J'ai peur que ma base de données soit corrompue car j'obtiens cette erreur. Comment puis-je corriger mon problème et obtenir cet index sur la table?

11
user2904235

Juste un pointeur sur: SQL Server 2017 (où je frappais cette erreur) et certaines versions de 2016 pour potentiellement gagner du temps aux autres:

Avant SQL Server 2017 CU8 (également 2016 SP1 CU9 et 2016 SP2 CU1), il y avait un problème où les tables partitionnées avec des statistiques incrémentielles généraient cette erreur si l'opération DML provoquait une mise à jour automatique des statistiques.

La page KB minimale est ici:

https://support.Microsoft.com/en-us/help/4163478/fix-access-violation-when-incremental-statistics-automatically-updated

L'installation d'une CU plus récente que celles répertoriées ci-dessus résout le problème.

4
cbailiss

Cela peut être causé par la corruption d'index,

La meilleure façon de gérer cela est de supprimer l'ancien index qui est corrompu.

DROP INDEX dbo.CO_DES_INPUT.IX_CO_DES_INPUT 

Et que Exécuter la requête en questions, cela devrait fonctionner correctement si tous les enregistrements sont uniques. dans les colonnes données.

3
MarmiK

Dans une base de données configurée pour les groupes de disponibilité Always On, vous pouvez également rencontrer ce problème si le groupe de disponibilité est en mode SYNCHRONOUS et que les secondaires sont hors ligne ou suspendus. Il s'agit d'un effet secondaire rencontré par les serveurs d'applications. Merci,

3
Kangeles

Quelque chose que j'ai involontairement trouvé: lorsque vous désactivez/reconstruisez des index sur une vue indexée, vous obtiendrez cette même erreur si vous essayez de reconstruire un ou plusieurs index non cluster avant de construire le cluster ou d'utiliser RECONSTRUIRE TOUT.

2
PseudoToad

J'obtiens toujours cette erreur lorsque j'ai une requête en cours, en utilisant un écouteur Always On AG, en utilisant l'une des bases de données AG et qu'il y a un basculement:

. Fournisseur de données Net SqlClient: Msg 596, niveau 21, état 1, ligne 0 Impossible de poursuivre l'exécution car la session est en mode d'arrêt. .Net SqlClient Data Provider: Msg 0, niveau 20, état 0, ligne 0 Une erreur grave s'est produite sur la commande en cours. Les résultats, le cas échéant, doivent être ignorés.

Très facile à reproduire! Bien sûr, il peut y avoir d'autres raisons, mais c'est le cas particulier où j'obtiens ce type d'erreur ...

2
HansLindgren

Je peux reproduire ce problème dans un programme C # assez petit qui utilise des connexions asynchrones, mais je ne suis pas sûr à 100% pourquoi. Voici mon programme de repro au cas où d'autres voudraient l'essayer - je soupçonne qu'il y a une série de choses qui doivent parfaitement s'aligner pour que cela se produise:

  • Pool de connexions activé
  • Utilisation de l'emprunt d'identité dans le pool de connexions, interdiction de rétablir ce contexte d'emprunt d'identité dans le pool de connexions
void Main()
{
    var impersonateMyself = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

    var testCommand = "SELECT TOP 1 * FROM sys.objects";
    var calls = Enumerable.Repeat(
        $@"{testCommand};",
        10
    );
    var impersonatedCalls = Enumerable.Repeat(
        $@"EXECUTE AS LOGIN = '{impersonateMyself} WITH NO REVERT';  {testCommand}; REVERT;",
        10
    );
    Dictionary<string, object> dict = new Dictionary<string, object>()
    {
    };

    // Scenario 1: Impersonated Calls, With connection pooling -- will randomly fail
    Parallel.ForEach(
        impersonatedCalls,
        c => new SqlAsync("Data Source=devsql2;Initial Catalog=Test;Integrated Security=true;Max Pool Size=2;").AsyncSqlCall<List<A>>(c, CommandType.Text, handleResultAsync, dict).Dump());

    Parallel.ForEach(
        impersonatedCalls,
        c => new SqlSync("Data Source=devsql2;Initial Catalog=Test;Integrated Security=true;Max Pool Size=2;").SyncSqlCall<List<A>>(c, CommandType.Text, handleResultSync, dict).Dump());


    // Scenario 2: Normal calls, with connection pooling -- should succeed every time
    Parallel.ForEach(
        calls,
        c => new SqlAsync("Data Source=devsql2;Initial Catalog=Test;Integrated Security=true;Max Pool Size=2;").AsyncSqlCall<List<A>>(c, CommandType.Text, handleResultAsync, dict).Dump());

    Parallel.ForEach(
        calls,
        c => new SqlSync("Data Source=devsql2;Initial Catalog=Test;Integrated Security=true;Max Pool Size=2;").SyncSqlCall<List<A>>(c, CommandType.Text, handleResultSync, dict).Dump());



// Scenario 3: Impersonated Calls, WITHOUT connection pooling -- should succeed every time
    Parallel.ForEach(
        impersonatedCalls,
        c => new SqlAsync("Data Source=devsql2;Initial Catalog=Test;Integrated Security=true;Max Pool Size=200;").AsyncSqlCall<List<A>>(c, CommandType.Text, handleResultAsync, dict).Dump());

    Parallel.ForEach(
        impersonatedCalls,
        c => new SqlSync("Data Source=devsql2;Initial Catalog=Test;Integrated Security=true;Max Pool Size=200;").SyncSqlCall<List<A>>(c, CommandType.Text, handleResultSync, dict).Dump());
}

public class SqlSync
{
    private readonly string _connectionString;
    public int Timeout {get; set;}

    public SqlSync(string connString)
    {
        _connectionString = connString;
        Timeout = 30;
    }

    public T SyncSqlCall<T>(string commandText, CommandType type, Func<SqlDataReader, T> handleResult, Dictionary<string, object> parameters = null)
    {
        using (SqlConnection conn = new SqlConnection(_connectionString))
        using (SqlCommand cmd = new SqlCommand(commandText, conn))
        {
            cmd.CommandTimeout = Timeout;
            cmd.CommandType = CommandType.Text;

            if (parameters != null)
            {
                foreach (KeyValuePair<string, object> kvp in parameters)
                    cmd.Parameters.AddWithValue(kvp.Key, kvp.Value ?? DBNull.Value);
            }

            conn.Open();

            using (var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                return handleResult(rdr);
        }
    }
}

public class SqlAsync
{
    private readonly string _connectionString;
    public int Timeout { get; set; }

    public SqlAsync(string connString)
    {
        _connectionString = connString;
        Timeout = 30;
    }

    public Task<T> AsyncSqlCall<T>(string sp, CommandType commandType, Func<SqlDataReader, Task<T>> handleResult, Dictionary<string, object> parameters = null)
    {
        return AsyncSqlCall<T>(sp, commandType, (reader, token) => handleResult(reader), CancellationToken.None, parameters);
    }

    public async Task<T> AsyncSqlCall<T>(string commandText, CommandType type, Func<SqlDataReader, CancellationToken, Task<T>> handleResult, CancellationToken cancellationToken, Dictionary<string, object> parameters = null)
    {
        using (SqlConnection conn = new SqlConnection(_connectionString))
        using (SqlCommand cmd = new SqlCommand(commandText, conn))
        {
            cmd.CommandTimeout = Timeout;
            cmd.CommandType = CommandType.Text;

            if (parameters != null)
            {
                foreach (KeyValuePair<string, object> kvp in parameters)
                    cmd.Parameters.AddWithValue(kvp.Key, kvp.Value ?? DBNull.Value);
            }

            await conn.OpenAsync(cancellationToken);

//          if (conn.State != ConnectionState.Open)
//              await Task.Delay(TimeSpan.FromMilliseconds(10));
            using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection, cancellationToken))
                return await handleResult(rdr, cancellationToken);
        }
    }
}

public class A
{
    public string object_name { get; set; }
}

public static Func<SqlDataReader, Task<List<A>>> handleResultAsync = (SqlDataReader sdr) =>
{
    var result = new List<A>();
    while (sdr.Read())
    {
        result.Add(new A { object_name = sdr.GetFieldValue<string>(0) });
    }
    return Task.FromResult(result);
};

public static Func<SqlDataReader, List<A>> handleResultSync = (SqlDataReader sdr) =>
{
    var result = new List<A>();
    while (sdr.Read())
    {
        result.Add(new A { object_name = sdr.GetFieldValue<string>(0) });
    }
    return result;
};
0
John Zabroski