Выберите MAX (поле) +1 FROM … Проблемы параллелизма
Привет, я боюсь, что параллелизм в партнерском приложении вызывает в последние дни проблемы с операциями CRUDS, особенно со вставками. Поэтому я запустил SQL Profiler и заметил, что его оператор insert не использует транзакцию, а также использует:
INSERT INTO TABLEA VALUES ( (SELECT MAX(NUMBERFIELD) +1 FROM TABLEA), ....);
Как избежать использования MAX () + 1 для генерации первичных ключей? Я предлагаю использовать автоинкрементные или транзакционные области, но он не хочет, или, может быть, он не знает, как этого достичь, есть ли другой способ для этого?
Использование SQL и C ++ 1.1
- Бесконечные дискуссии: атомные вставки, блокировка и транзакции в SQL Server. Он заканчивается здесь
- Избегание дубликатов при одновременном считывании с той же таблицы базы данных
- Выбор запроса пропускает записи во время параллельных обновлений
- Entity Framework IsRowVersion () без проверки параллелизма
- В SQL Server, как я могу заблокировать одну строку так же, как Oracle SELECT FOR UPDATE WAIT?
* Его не мой код, но я мог бы подумать, покажу ему этот пост, потому что я думаю, что он должен учитывать, что все мнения приветствуются. 🙂
- Какие намеки на блокировку следует использовать (T-SQL)?
- Как один SELECT блокирует другой?
- Оптимистический параллелизм: IsConcurrencyToken и RowVersion
- Каковы последствия SET-ting ALLOW_SNAPSHOT_ISOLATION ON?
- MS SQL Server - безопасное одновременное использование глобальной таблицы temp?
- Как выбрать правильный механизм параллелизма / блокировки с помощью Entity Framework
- Только вставляя строку, если она еще не существует
Если вы правильно это сформулируете, вы сможете получить такую же параллельность из этого, как с решением IDENTITY. Это не интуитивно; вы могли бы подумать, что блокировка уменьшит параллелизм. Но я провел несколько тестов с пятью различными соединениями, забирая стол, и показал себе, что трюк MAX + 1 работает примерно так же, как IDENTITY. Вы можете ознакомиться с обсуждением в первом разделе следующего сообщения в блоге:
Во всяком случае, вот синтаксис, который я рекомендую (я действительно не доверяю модели INSERT … VALUES (SUBQUERY), извините):
DECLARE @NextID INT; BEGIN TRANSACTION; SELECT @NextID = COALESCE(MAX(NumberColumn), 0) + 1 FROM dbo.TableA WITH (UPDLOCK); INSERT dbo.TableA SELECT @NextID; COMMIT TRANSACTION;
Вы должны представить части обработки ошибок (опущены для краткости), но я думаю, что вы получите дрейф.
Разумеется, для Евангелия это не принимается. Вам нужно будет запустить тесты на вашем оборудовании, используя ваши данные и шаблоны доступа, чтобы определить, будет ли этот метод нарушен параллелизм. Это вполне может быть одним из ответов «это зависит».
Рассматривали ли вы создание первичного ключевого столбца IDENTITY
? Это заставит SQL Server автоматически генерировать значения для столбца:
CREATE TABLE Test ( Id int identity primary key not null -- ... )