AlwaysEncrypted Вставить сбои периодически - PullRequest
0 голосов
/ 13 февраля 2019

Мы используем функцию AlwaysEncrypted Microsoft SQL уже более года.До сих пор это работало без нареканий.Ранее у нас было только несколько зашифрованных столбцов (4).Неделю назад мы внедрили шифрование еще в 11 столбцах, поэтому по-прежнему используем его очень легко.

К сожалению, некоторые из наших команд «INSERT» для таблиц с зашифрованными столбцами не выполняются, , нотолько с перерывами .Команды выполняются веб-сервером (сервером IIS).Я могу выполнить команду, если она завершится с ошибкой, и сразу же после того, как будет сгенерировано исключение, выполнить ту же команду в том же процессе (веб-сервер просто обработал исключение), и она завершится успешно.

Двоичный файл серверанаписано на c #, а команды абсолютно тривиальны.Например, выполнение этой команды завершается неудачно:

INSERT INTO [dbo].[someTable] ( [COL1], [COL2], [COL3] ) VALUES ( @COL1_0, @COL2_0, @COL3_0 )

, где все три столбца (COL1, COL2 и COL3) зашифрованы, а [someTable] имеет только эти три столбца, все varchar(64) плюс столбец целочисленных идентификаторов.

код c # (перефразированный):

        SqlCommand cmd = new SqlCommand();
        cmd.Connection = GetOpenConnection("Data Source=REDACTED;Integrated Security=SSPI;Column Encryption Setting=enabled;Initial Catalog=PRODUCTION");
        cmd.CommandText = "INSERT INTO [dbo].[someTable] ( [COL1], [COL2], [COL3] ) VALUES ( @COL1_0, @COL2_0, @COL3_0 )";
        cmd.CommandType = CommandType.Text;
        cmd.Transaction = m_Transaction;            

        foreach(string[] paramData in inputParamsData) //3 of these
        {
                                                      //@COLx_0
            SqlParameter param = new SqlParameter(paramData[0], SqlDbType.VarChar, 64);
            param.Value = paramData[1];
            cmd.Parameters.Add(param);
        }
        string msg = "Preparing";
        try
        {
            cmd.Prepare();
            msg = "Executing";
            return cmd.ExecuteNonQuery();
        }
        catch (Exception ex)
        {
            if (ex.Message.Contains("Operand type clash"))
            {
                log.Error($"{msg} non-query", ex);
                log.Error("Parameters in command");
                foreach (var obj in command.Parameters)
                {
                    SqlParameter param = obj as SqlParameter;
                    if (param != null)
                    {
                        log.ErrorFormat("Param name: {0}, length: {1}", param.ParameterName, param.Size);
                    }
                }
            }
            throw;
        }

Ошибка выполнения ExecuteNonQuery() (хотя в тексте сообщения об исключении говорится, что он не может «подготовить» запрос, проверка ведения журнала)сообщения проясняют, что Prepare завершается успешно, а ExecuteNonQuery завершается неудачей.) Получаемое нами логирование:

2019-02-21 23:15:43,046 ERROR [15:xxx.DbConnectionWrapper`6] - Executing non-query
System.Data.SqlClient.SqlException (0x80131904): Operand type clash: varchar is incompatible with varchar(64) encrypted with (encryption_type = 'DETERMINISTIC', encryption_algorithm_name = 'AEAD_AES_256_CBC_HMAC_SHA_256', column_encryption_key_name = 'ColumnKey_20180605_123456', column_encryption_key_database_name = 'Production') collation_name = 'Latin1_General_BIN2'
Statement(s) could not be prepared.
...
Error Number:206,State:2,Class:16
2019-02-21 23:15:43,067 ERROR [15:xxx.DbConnectionWrapper`6] - Parameters in command
2019-02-21 23:15:43,069 ERROR [15:xxx.DbConnectionWrapper`6] - Param name: @FIGI_0, length: 64

Видно, что размер параметра действительно установлен правильно.Единственный столбец, который зашифрован, это столбец «FIGI», который является столбцом varchar (64), и параметр, по-видимому, задан правильно.

У нас есть Microsoft SQL Server Enterprise (64-разрядная версия),версия 13.0.5026.0.Сервер IIS имеет .NET 4.6.1.

Кто-нибудь испытывал такие периодические сбои?У кого-нибудь есть указатели, где искать проблему?

Замечу, что класс SqlParameter имеет свойство ForceColumnEncryption, но очень мало документации, чтобы указать, когда, где или как этот параметр должениспользоваться.Кто-нибудь может объяснить его использование или указать мне на достойную документацию?

Редактировать: оказывается, что прерывистый характер хуже, чем этот.Это терпит неудачу только приблизительно один раз в неделю.Приведенные ниже комментарии относительно размера параметров я добавил в некоторые журналы отладки, когда они не работают, с результатами, как указано выше.

...