Являются ли временные таблицы поточно-ориентированными? - PullRequest
43 голосов
/ 21 января 2009

Я использую SQL Server 2000, и во многих хранимых процедурах он широко использует временные таблицы. В базе данных много трафика, и меня беспокоит безопасность потоков при создании и удалении временных таблиц.

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

  • Возможно ли, чтобы один пользователь запустил sp и который создал временную таблицу с именем #temp, а другой пользователь запустил тот же sp, но был остановлен, поскольку в базе данных уже существует таблица с именем #temp?

  • Как насчет того, если один и тот же пользователь выполняет одну и ту же хранимую процедуру дважды для одного и того же соединения?

  • Существуют ли какие-либо другие странные сценарии, которые могут привести к тому, что запросы двух пользователей будут мешать друг другу?

Ответы [ 9 ]

33 голосов
/ 21 января 2009

В первом случае нет, это невозможно, поскольку #temp является локальной временной таблицей и поэтому невидим для других подключений (предполагается, что ваши пользователи используют отдельные подключения к базе данных). Имя временной таблицы связывается со случайным именем, которое генерируется, и вы ссылаетесь на него, когда ссылаетесь на локальную временную таблицу.

В вашем случае, поскольку вы создаете локальную временную таблицу в хранимой процедуре, эта временная таблица будет удалена при выходе из области действия процедуры (см. «Раздел примечаний»).

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

8 голосов
/ 22 января 2009

Временные таблицы локальной области (с одним #) создаются с идентификатором в конце, который делает их уникальными; несколько абонентов (даже с одним и тем же логином) никогда не должны перекрываться.

(Попробуйте: создайте одну и ту же временную таблицу из двух подключений и одного и того же имени входа. Затем запросите объекты tempdb.dbo.sys для просмотра созданных реальных таблиц ...)

5 голосов
/ 08 мая 2012

Локальные временные таблицы являются поточно-ориентированными, поскольку они существуют только в текущем контексте. Пожалуйста, не путайте контекст с текущим соединением (от MSDN : «Локальная временная таблица, созданная в хранимой процедуре, автоматически удаляется по завершении хранимой процедуры»), одно и то же соединение может безопасно вызвать два или более раз хранимая процедура, которая создает локальную временную таблицу (например, #TMP).

Вы можете проверить это поведение, выполнив следующую хранимую процедуру из двух соединений. Этот SP будет ждать 30 секунд, поэтому мы можем быть уверены, что два потока будут одновременно запускать свои собственные версии таблицы #TMP:

CREATE PROCEDURE myProc(@n INT)
AS BEGIN
    RAISERROR('running with (%d)', 0, 1, @n);
    CREATE TABLE #TMP(n INT);
    INSERT #TMP VALUES(@n);
    INSERT #TMP VALUES(@n * 10);
    INSERT #TMP VALUES(@n * 100);
    WAITFOR DELAY '00:00:30';
    SELECT * FROM #TMP;
END;
4 голосов
/ 18 июля 2017

Краткий ответ:

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

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

Локальные временные объекты разделяются Сеанс на SQL-сервере. Если у вас есть два запроса, выполняющихся одновременно, то это два совершенно разных сеанса, которые не будут мешать друг другу. Имя входа не имеет значения, поэтому, например, если вы используете одну строку подключения с использованием ADO.NET (это означает, что несколько одновременных запросов будут использовать один и тот же SQL-сервер 'login'), все ваши запросы будут по-прежнему выполняться в отдельных сессий . Пул подключений также не имеет значения. Локальные временные объекты (таблицы и хранимые процедуры) полностью защищены от просмотра другими сеансами .

Чтобы уточнить, как это работает; в то время как ваш код имеет одно общее имя для локальных временных объектов, SQL Server добавляет уникальную строку к каждому объекту для каждого сеанса, чтобы держать их отдельно. Вы можете увидеть это, запустив в SSMS следующее:

CREATE TABLE #T (Col1 INT)

SELECT * FROM tempdb.sys.tables WHERE [name] LIKE N'#T%';

В имени вы увидите что-то вроде следующего:

T * _______________ 00000000001F 1028 * Затем, не закрывая эту вкладку запроса, откройте новую вкладку запроса, вставьте в тот же запрос и снова запустите его. Теперь вы должны увидеть что-то вроде следующего: T * _______________ 00000000001F * тысяча тридцать два T * _______________ 000000000020 * 1034 Таким образом, каждый раз, когда ваш код ссылается на #T, SQL Server будет переводить его на правильное имя в зависимости от сеанса. Разделение обрабатывается автоматически.

3 голосов
/ 21 января 2009

Временные таблицы привязаны к сеансу, поэтому, если разные пользователи запускают вашу процедуру одновременно, нет конфликта ...

1 голос
/ 21 января 2009

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

1 голос
/ 21 января 2009

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

0 голосов
/ 22 января 2009

Сначала давайте удостоверимся, что вы используете реальные временные таблицы, они начинаются с # или ##? Если вы создаете настоящие таблицы на лету, а затем повторно удаляете и воссоздаете их, у вас действительно будут проблемы с одновременными пользователями. Если вы создаете глобальные временные таблицы (начинающиеся с ##), у вас также могут возникнуть проблемы. Если вы не хотите проблем с параллелизмом, используйте локальные временные таблицы (они начинаются с #). Хорошей практикой также является явное закрытие их в конце процесса (или когда они больше не нужны процессу, если вы говорите о длинных многошаговых процессах) и проверка на существование (и удаление, если так) перед созданием ,

0 голосов
/ 22 января 2009

если вы не используете два знака фунта ## temp, временная таблица будет локальной и существует только для этого локального соединения с пользователем

...