Два (ВЫБРАТЬ ТОП 1 +1) утверждения и два ВСТАВКИ одновременно - PullRequest
3 голосов
/ 10 марта 2019

Что произойдет, если во время выполнения транзакции другой клиентский компьютер выполняет вставку?

У меня есть два клиентских компьютера и одна БД.На этих компьютерах установлена ​​одна и та же программа.Допустим, у нас есть таблица заказов и столбец salesorder #, этот столбец UNIQUE.

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

@ordernumber= SELECT TOP Salesorder# +1 .
 INSERT INTO order (salesorder#,dateship, user) VALUES (@ordernumber,GETDATE(),1,)

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

Что происходит в другом сценарии.Если транзакция начинается, и другой оператор INSERT (не оператор TRANSACTION Just INSERT) запрашивается после оператора SELECT, но до того, как произойдет INSERT.

Что будет делать SQL Server в этой ситуации?Это вообще возможно?

Ответы [ 2 ]

1 голос
/ 10 марта 2019

Одно слово: НЕ ДЕЛАЙТЕ ЭТОГО !! Это БУДЕТ сбой - наверняка.

Предполагается, что у вас есть таблица снаибольшее число 100 - теперь у вас есть два (или несколько) одновременных пользовательских запроса на вставку.

Оба запроса сначала читают наибольшее число (100), и каждый увеличивает его на +1 - так что обаимеют значение 101 внутри.Оператор SELECT будет выполнять только быструю общую блокировку - но оба SELECT будут работать и будут читать значение 100. Независимо от того, находятся они внутри транзакции или нетздесь нет никакой разницы - просто потому, что транзакция не останавливает секунду SELECT.

INSERT на самом деле создаст эксклюзивную блокировку- но только для вставляемой строки ( НЕ всей таблицы!).Ничто не мешает обоим одновременным запросам вставить их новую строку, и оба будут пытаться вставить строку со значением salesorder#, равным 101. Если у вас есть уникальное ограничение на это, один из запросов завершится с ошибкой так как другой запрос уже вставил значение 101.

Это одна из многих причин, по которой вы должны NOT обрабатывать выдачу последовательных идентификаторов вручную - пусть база данных обрабатывает их, используястолбец INT IDENTITY или объект SEQUENCE.

0 голосов
/ 10 марта 2019

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

Наша архитектура программного обеспечения сосредоточена в шлюзе.Таким образом, у нас есть клиенты, отправляющие команду шлюзу, а затем шлюз связывается с SQL SERVER.Я сделаю так, чтобы шлюз не отправлял команду INSERT в одну и ту же таблицу в одно и то же время, отдавая приоритет клиентам по-разному.

Например: если у нас есть клиенты compuerta, давайте назовем их 1,23.Сделайте то же самое действие в то же время.(Я знаю, что это технически невозможно). Я могу присвоить приоритет 1, затем, когда 1 закончится, 2 выполнится, а затем 3.Я знаю, что это не решение с помощью SQL, потому что таким образом я предотвратим неудачную вставку и смогу сохранить IDENTITY для продавца #.Ограничение времени, в течение которого произошла бы неудачная вставка, составило бы почти 0.

Еще раз спасибо за всю помощь и объяснения, почему бы не ВСТАВИТЬ, как я хотел сделать раньше.Какие книги рекомендуются для чтения на базе данных?

...