IDENTITY_INSERT ON
Kendi başına ayarlamak eşzamanlılığı ortadan kaldırmaz - bu masaya herhangi bir özel kilit yerleştirmez, sadece kısa bir şema kararlılığı (Sch-S) kilidi.
Teorik olarak, varsayılan davranış altında ne olabilir, bunu oturum 1'de yapabilirsiniz:
BEGIN TRANSACTION;
-- 1
SET IDENTITY_INSERT dbo.tablename ON;
-- 2
INSERT dbo.tablename(id, etc) VALUES(100, 'foo'); -- next identity is now 101
-- 3
INSERT dbo.tablename(id, etc) VALUES(101, 'foo'); -- next identity is now 102
-- 4
SET IDENTITY_INSERT dbo.tablename OFF;
COMMIT TRANSACTION;
Başka bir oturumda, 1, 2, 3 veya 4. noktalarda tabloya satır ekleyebilirsiniz. Bu, iyi bir şey gibi görünebilir , ancak 2 ile 3 arasında gerçekleşen herhangi bir ek için ne olduğu dışında, otomatik olarak oluşturulan değerin tetiklenmesi başka bir oturumda ise deyim 2'nin sonuçları temel alınır - bu nedenle 101 oluşturur ve deyim 3 birincil anahtar ihlaliyle başarısız olur. Bazı WAITFOR
s ile kendinizi kurmak ve test etmek oldukça basittir :
-- session 1
-- DROP TABLE dbo.what;
CREATE TABLE dbo.what(id INT IDENTITY PRIMARY KEY);
GO
BEGIN TRANSACTION;
SET IDENTITY_INSERT dbo.what ON;
INSERT dbo.what(id) VALUES(32);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(33);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(34);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(35);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(36);
SET IDENTITY_INSERT dbo.what OFF;
COMMIT TRANSACTION;
Bu toplu işlem başladığında, bu toplu işi başka bir pencerede başlatın:
-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20
2. Oturum, yalnızca 1-20 arasındaki değerleri eklemelidir, değil mi? Bunun dışında, temel kimlik el ile eklenen oturum 1'iniz tarafından güncellendiğinden, bir noktada oturum 2'nin oturum 1'in kaldığı yerden devam edeceği ve 32, 33 veya 34 vb. Ekleneceği kabul edilir, ancak bunun yapılmasına izin verilir, ancak daha sonra oturum 1, PK ihlali ile bir sonraki ekte başarısız olur (ki bu kazanma yalnızca bir zamanlama meselesi olabilir).
Bunu geçici olarak çözmenin bir yolu TABLOCK
, ilk ekte a çağırmaktır :
INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);
Bu, arşivlenen satırları geri taşıyana kadar bu tabloyu eklemeye (veya gerçekten bir şey yapmaya) çalışan diğer kullanıcıları engeller. Bu eşzamanlılığı daraltıyor, elbette, ancak engellemenin çalışmasını istediğiniz yol budur . Ve umarım bu, diğer insanları her zaman engellediğiniz kadar sık görülen bir şey değildir.
Diğer birkaç geçici çözüm:
IDENTITY
üretilen değerin bakımını durdurun . Kimin umrunda? Bir kullanma UNIQUEIDENTIFIER
(belki ile ayrı bir tabloda oluşturulan IDENTITY
orijinal değeri çok önemli ise bir yedek olarak).
- başlangıçta arşivlenmiş olarak işaretlenen ve arşivin daha sonraki bir tarihe kadar kalıcı olmadığı bir "yumuşak silme" kullanmak için arşivleme işlemini değiştirin. Daha sonra, onları geri almaya çalışan her işlem doğrudan bir güncelleme yapabilir ve yumuşak silme bayrağını düzeltebilir.