Использование SPID в таблицах БД (вместо переменной таблицы)

8

Транзакционная база данных, используемая для бронирования вещей ...

Нашего поставщика попросили заменить #temptables на @tablevariables (из-за сильных блокировок компиляции), но вместо этого они заменили фактическую таблицу, которая добавляет SPID в качестве столбца, чтобы гарантировать, что хранимая процедура действует только на соответствующие строки.

Видите ли вы какой-либо риск в этом методе работы? До того, как все транзакции были изолированы внутри их собственной транзакции ... Я беспокоился, что мы можем блокировать эту таблицу, но их мнение таково, что SQL использует блокировку на уровне строк, и это не создаст больше блокировок.

Версия SQL Server: 2016 Enterprise - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

outjet
источник
1
Это зависит. Сколько сеансов одновременно используют таблицу, насколько активны указанные сеансы, сколько записей в таблице, очищены ли записи в этой новой таблице или они остаются и т. Д.? 5 сеансов, ничего страшного. 500 сессий, вполне вероятно, что вы столкнетесь с блокировкой, которую вы не увидите с временными таблицами / переменными, локальными для каждого сеанса.
Джон Айсбренер
Какую версию сервера sql вы используете?
Энтони Дженовезе
2016 Enterprise - 13.0.5216.0
outjet
Количество записей в таблице попаданий за сеанс будет 1-50 ... они будут очищены, так что сама таблица, вероятно, не получит более 1000 строк одновременно ... одновременных сеансов, вероятно, около 50 ....
outjet
1
Если вы вынуждены пойти по этому пути (пожалуйста, постарайтесь избежать этого), я бы серьезно подумал о разбиении значения spid, убедившись, что для повышения блокировки в таблице установлено значение AUTO. Тогда, по крайней мере, очистка данных конкретного spid может быть выполнена в операции переключения и усечения.
Джонатан

Ответы:

5

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

  • родительский процесс (Common_InsertOrders_1) создает временную таблицу
  • дочерний процесс (InsertOrders) запрашивает временную таблицу
  • наблюдаются блокировки компиляции для дочернего процесса (InsertOrders)

Sybase ASE ... немного помешает на минутку ... что случится с этим сценарием ...

  • каждая временная таблица получает уникальный идентификатор объекта (конечно, идентификатор объекта может быть использован повторно в какой-то момент, но это редко, и, конечно, не произойдет для одновременных сеансов)
  • Sybase ASE обычно вызывает принудительную перекомпиляцию при каждом выполнении дочернего процесса из-за изменения идентификатора объекта для временной таблицы
  • Sybase ASE также принудительно выполнит перекомпиляцию дочернего процесса, если обнаружит, что структура временной таблицы изменилась (например, разное количество столбцов, разные имена столбцов / типы данных / обнуляемость) между хранимыми вызовами процесса
  • более поздние версии Sybase ASE имеют конфигурацию, которая (эффективно) указывает компилятору игнорировать изменения в идентификаторах объектов временной таблицы, тем самым устраняя перекомпиляцию дочернего процесса (ПРИМЕЧАНИЕ: перекомпиляция все равно будет происходить, если структура таблицы изменится)

Вернемся к проблеме OP (блокировка компиляции дочернего процесса) ...

  • есть ли вероятность того, что некоторые признаки поведения Sybase ASE все еще могут находиться в SQL Server (с тех пор, как два продукта были в горохе)?
  • Существуют ли какие-либо конфигурации SQL Server, которые могут уменьшить (устранить?) перекомпиляцию дочернего процесса (если из-за изменений в идентификаторе объекта)?
  • Может ли OP проверить, что родительский процесс создает временную таблицу с одинаковой точной структурой / DDL каждый раз?

Что касается идеи использовать одну постоянную таблицу с @@ SPID для разграничения строк между сеансами ... был там, видел, что ... yuck ; повторяющиеся проблемы:

  • как / когда убирать сиротские ряды
  • повторное использование @@ SPID механизмом базы данных может привести к проблемам с точностью данных, если существуют потерянные данные (или во время очистки потерянных данных, например, удалить где @@ SPID = 10, но есть новый / текущий / активный сеанс с @ @ SPID = 10 => очистка удаляет слишком много данных)
  • возможность повышения блокировки от блокировок строк до блокировок страниц / таблиц
  • если таблица имеет индексы, то потенциальная (b) блокировка при обновлении индексов
  • в зависимости от того, в какой базе данных находится таблица, вы можете искать гораздо больше действий для записи на устройство регистрации (в Sybase ASE можно эффективно отключить регистрацию в базе данных tempdb)
  • даже (исключительные) блокировки на уровне строк могут блокировать другие сеансы (зависит от уровня изоляции и от того, может ли сеанс сканировать / пропустить / пропустить указанные исключительные блокировки)

Я хотел бы вернуться и (повторно) исследовать корневую проблему (блокировки перекомпиляции на дочернем процессоре) и посмотреть, есть ли способ уменьшить (устранить?) Указанные блокировки компиляции. [К сожалению, мои знания SQL Server по этим вопросам ... NULL ... поэтому я хотел бы узнать мнение некоторых экспертов по компилятору SQL Server.]

markp-Fuso
источник
1
Я согласен, я думаю, что больше времени нужно потратить на исследование блокировок компиляции. Это имеет несколько моментов для расследования. support.microsoft.com/en-us/help/263889/…
Джонатан
8

Мне кажется, что @@SPIDподобное использование вызывает проблемы.

Идентификаторы сеансов часто используются повторно; как только пользовательское соединение выходит из системы, этот идентификатор сеанса становится доступным для повторного использования и, вероятно, будет использоваться следующим сеансом, пытающимся подключиться.

Чтобы заставить его работать хотя бы частично надежно, вам потребуется триггер входа в систему, который удаляет предыдущие строки из таблицы с тем же @@SPID. Если вы сделаете это, вы, вероятно, увидите много блокировок таблицы, используя @@SPIDстолбец.

SQL Server действительно использует блокировку строк, но он также использует блокировку страниц и таблицы. Конечно, вы можете смягчить это с помощью хорошей индексации, но для меня это все еще выглядит как анти-паттерн.

Если хранимая процедура является единственным методом, используемым для доступа к затронутым таблицам, вы можете исследовать, используя блокировку приложения, по sp_getapplockсуществу для сериализации доступа к соответствующим частям. Документы для sp_getapplock здесь . У Эрика Дарлинга есть интересный пост об этом здесь .

Макс Вернон
источник
4

Да, я вижу риски. Наивно рассчитывать на SQL с помощью Row Locking. Например, я уверен, что при вставке и удалении будут по крайней мере использоваться блокировки страниц. SQL Engine выбирает тип блокировки на основе нескольких факторов, и ни один из этих факторов не включает «их мнение». Общие решения, такие как замена временных таблиц на переменные таблиц, как правило, тоже плохие идеи. Переменные таблицы очень полезны в некоторых ситуациях, но у них есть ограничения и проблемы с производительностью. Я предпочитаю временные таблицы в большинстве случаев. Особенно когда таблица будет содержать более нескольких десятков строк. Я бы потребовал, чтобы поставщик объяснил, почему система испытывает «сильные блокировки компиляции» и как это снижает производительность. Помните, что каждый раз, когда вы смотрите, вы найдете «тяжелые замки» какого-то рода. Это не обязательно означает, что замки являются проблемой. Максимум' s комментарии о @@ SPID также важны. Кроме того, модель транзакций и обработка ошибок могут быть большими проблемами. Если ваша система испытывает взаимные блокировки или проблемы с качеством входных данных, то стандартная обработка ошибок может привести к завершению сеанса без надлежащей перезагрузки таблицы qryTransactions. ИМО неправильный подход к решению исходной проблемы.

луч
источник
Спасибо за ответ - к вашим точкам: наши следы показывают, что тяжелый LCK ждет блокировки компиляции на хранимой процедуре InsertOrders. Существует родительская процедура Common_InsertOrders_1, которая объявляет временную таблицу #qryTransactions, а затем вложенную процедуру InsertOrders_2 запрашивает временную таблицу. Кроме того, мы узнали, что есть также частая перекомпиляция, потому что после 6 модификаций пустой временной таблицы, любая хранимая процедура,
outjet
Есть много причин, по которым процедура или утверждение будут перекомпилированы. MarkP упомянул ряд из них, которые применяются в SyBase, и я уверен, что SQL Server похож. Хорошим примером является количество строк в таблице временных таблиц, а перекомпиляция - не обязательно плохая вещь. Статистика таблицы может существенно изменить оптимальный план запроса, и для его определения требуется перекомпиляция. Но я хочу повторить. ВСЕГДА будет верхняя блокировка, и это не означает, что блокировка является проблемой. Если вы не видите других доказательств проблемы с производительностью, не беспокойтесь об этом.
Рэй