Когда именно несколько пользователей не могут одновременно запустить хранимую процедуру с временной таблицей?

9

У меня есть вопрос, касающийся части документации по временным таблицам, которую я недавно прочитал в TechNet . Четвертый абзац раздела « Временные таблицы » на этой странице гласит:

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

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

В частности, мне неясно по следующим пунктам:

  1. Это относится только к глобальным временным таблицам или к локальным? Кажется странным, что таблица, которая не видна вне сеанса (как в последнем случае), помешала бы одновременному выполнению другого сеанса.
  2. Что квалифицируется как «именованное ограничение»? Разве все ограничения не имеют имен (даже если они генерируются системой)? Это относится к ограничениям с пользовательским псевдонимом? Это кажется мне плохой формулировкой.
  3. «Несколько пользователей» на самом деле означает несколько сеансов? Эти процедуры вызываются через наше приложение с использованием одной учетной записи службы, поэтому 99,9% обращений к нашим сценариям совершаются в БД с помощью этой единственной учетной записи (и я не беспокоюсь о случайных вызовах, которые администратор может сделать на сервере). Если служебная учетная запись может запускать sproc одновременно в нескольких сеансах, тогда эта проблема для меня не имеет значения.
Уэсли Маршалл
источник
1
Вы упоминаете, что ваши временные таблицы проиндексированы, но вопрос заключается в ограничениях. Индексы не являются ограничениями. То, что верно для одного, может или не может быть верно для другого. В этом случае имена индексов могут дублироваться в базе данных, в отличие от ограничений. Имена индексов не могут дублироваться в одной таблице. Таким образом, именованные индексы не вызовут проблем с именованными ограничениями.
Шеннон Северанс
@Shannon, действительно, в то время, когда я писал вопрос, я запутался в этом. Я думаю, что плодотворное использование PRIMARY KEY CLUSTERED и PRIMARY KEY, которое я видел в примере кода и документации, привело меня к мысли, что кластерные индексы являются ограничениями. И, как следствие, сделать вывод, что все индексы являются ограничениями. Раньше я немного читал днем, чтобы прояснить это для меня.
Уэсли Маршалл

Ответы:

10

Я думаю об этом, потому что у вас не может быть повторяющихся имен tempdb.sys.key_constraints. Вот что находится в этом представлении метаданных на одном из моих серверов:

первоначальный вид

Все нечетные имена, заканчивающиеся на, _6E...были автоматически сгенерированы SQL Server. Они не называются ограничениями, потому что я не дал им явно имя при их создании. SQL Server генерирует имя ограничения за кулисами, что теоретически позволяет избежать конфликтов имен.

Если я попытаюсь создать следующую таблицу в двух разных сессиях:

create table #x1 (
ID INT NOT NULL,
CONSTRAINT NAMED_CONSTRAINT_1 PRIMARY KEY (ID)
);

Тот, который запускается вторым, выдает ошибку:

Сообщение 2714, уровень 16, состояние 5, строка 1

В базе данных уже есть объект с именем NAMED_CONSTRAINT_1.

Сообщение 1750, уровень 16, состояние 1, строка 1

Не удалось создать ограничение или индекс. Смотрите предыдущие ошибки.

Еще раз проверяем вид:

с ограничением

Если я попытаюсь создать следующую таблицу за две сессии, это не проблема:

create table #y1 (
ID INT NOT NULL,
PRIMARY KEY (ID)
);

Вот представление метаданных:

с ограничениями по умолчанию

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

Джо Оббиш
источник
11

Это относится к локальным временным таблицам.

Разница между именованными и безымянными ограничениями заключается в следующем:

CREATE TABLE #t1 (c1 INT PRIMARY KEY CLUSTERED)

CREATE TABLE #t2 (c1 INT,
                     CONSTRAINT pk_c1 PRIMARY KEY  CLUSTERED(c1) )

Разрешение ограничения имени системы делает крайне маловероятным, что произойдет столкновение. В этом примере, если вы откроете два окна в SSMS, вы сможете создавать #t1в обоих, но не в #t2.

Глобальные временные таблицы являются общими для всех пользователей, поэтому вы должны обрабатывать их по-разному. Они не «уничтожаются» до тех пор, пока с их помощью не будет завершен последний сеанс, поэтому вам нужно убедиться, что когда пользователи обращаются к ним, они могут получить доступ только к своим данным. Иногда это делается с помощью SPID, а иногда - с помощью хеш-значения. Это зависит от того, как используется глобальная временная таблица.

Обычно для глобальных временных таблиц хранимые процедуры проверяют, существуют ли они, а затем создают их, только если они OBJECT_ID()есть NULL.

Несколько пользователей означает несколько сеансов. Логин не имеет к этому никакого отношения. Если Джордж бежит, sp_something @i = 1а Джина бежит sp_something @i = 2, не имеет значения, если они оба вошли в систему как User1, у них будут разные SPID.

Эрик Дарлинг
источник