Kapan tepatnya beberapa pengguna tidak dapat menjalankan prosedur tersimpan secara bersamaan dengan tabel temp?

9

Saya punya pertanyaan tentang sepotong dokumentasi tentang Tabel Temp yang baru-baru ini saya baca di TechNet . Paragraf keempat bagian Tabel Sementara pada halaman itu berbunyi sebagai berikut:

Jika tabel sementara dibuat dengan batasan bernama dan tabel sementara dibuat dalam lingkup transaksi yang ditentukan pengguna, hanya satu pengguna pada satu waktu yang dapat menjalankan pernyataan yang membuat tabel temp. Misalnya, jika prosedur tersimpan membuat tabel sementara dengan batasan kunci primer bernama, prosedur tersimpan tidak dapat dijalankan secara bersamaan oleh beberapa pengguna.

Saya bekerja di lingkungan di mana kami menggunakan secara signifikan beberapa prosedur tersimpan yang menggunakan tabel temp diindeks, dan kami tidak pernah mengalami masalah di mana pengguna harus menunggu satu eksekusi untuk menyelesaikan sebelum yang berikutnya dimulai. Saya harap itu akan terus menjadi masalah, tetapi saya khawatir hal itu bisa menjadi masalah jika peringatan ini tidak dipahami dengan baik.

Secara khusus, saya tidak jelas tentang hal-hal berikut:

  1. Apakah ini hanya berlaku untuk tabel temp global, atau yang temporer juga? Tampaknya aneh bahwa tabel yang tidak terlihat di luar sesi (seperti dalam kasus yang terakhir) akan mencegah sesi lain dari eksekusi secara bersamaan.
  2. Apa yang memenuhi syarat sebagai "batasan nama"? Tidak semua kendala memiliki nama (bahkan jika itu dihasilkan oleh sistem)? Apakah ini merujuk pada kendala dengan alias yang ditentukan pengguna? Ini sepertinya ungkapan yang buruk bagiku.
  3. Apakah "banyak pengguna" sebenarnya berarti beberapa sesi? Prosedur ini dipanggil melalui aplikasi kami menggunakan akun layanan tunggal, sehingga 99,9% panggilan ke skrip kami dilakukan ke DB oleh akun tunggal itu (dan saya tidak peduli tentang panggilan sesekali yang mungkin dilakukan admin di backend). Jika akun layanan dapat menjalankan sproc dalam beberapa sesi secara bersamaan, maka masalah ini diperdebatkan untuk tujuan saya.
Wesley Marshall
sumber
1
Anda menyebutkan bahwa tabel temp Anda diindeks tetapi pertanyaannya adalah tentang kendala. Indeks bukan kendala. Apa yang benar untuk yang satu mungkin atau mungkin tidak benar untuk yang lain. Dalam hal ini, nama indeks dapat digandakan dalam database, tidak seperti kendala. Nama indeks tidak dapat diduplikasi pada satu tabel. Indeks yang dinamai demikian tidak akan menyebabkan masalah bernama kendala akan.
Shannon Severance
@Shannon, memang, pada saat saya menulis pertanyaan, saya memiliki titik ini bingung. Saya berpikir bahwa penggunaan utama PRIMARY KEY CLUSTERED vs PRIMARY KEY yang saya lihat dalam kode sampel dan dokumentasi membuat saya percaya bahwa indeks berkerumun merupakan kendala. Dan, dengan ekstensi, untuk menyimpulkan bahwa semua indeks adalah kendala. Saya membaca sore yang ringan sebelumnya yang menjelaskan hal ini untuk saya.
Wesley Marshall

Jawaban:

10

Saya menganggapnya karena Anda tidak dapat memiliki nama duplikat di dalamnya tempdb.sys.key_constraints. Inilah yang ada di tampilan metadata di salah satu server saya:

tampilan awal

Semua nama aneh yang diakhiri dengan _6E...adalah nama yang dihasilkan secara otomatis oleh SQL Server. Mereka tidak bernama kendala karena saya tidak secara eksplisit memberi mereka nama saat membuat mereka. SQL Server menghasilkan nama kendala di belakang layar yang secara teori menghindari tabrakan nama.

Jika saya mencoba membuat tabel berikut dalam dua sesi berbeda:

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

Yang berjalan kedua melempar kesalahan:

Msg 2714, Level 16, Negara 5, Jalur 1

Sudah ada objek bernama 'NAMED_CONSTRAINT_1' dalam database.

Msg 1750, Level 16, Status 1, Baris 1

Tidak dapat membuat batasan atau indeks. Lihat kesalahan sebelumnya.

Lihat lagi tampilan:

dengan kendala

Jika saya mencoba membuat tabel berikut dalam dua sesi tidak ada masalah:

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

Berikut tampilan metadata:

dengan kendala standar

Hanya untuk menjawab pertanyaan Anda secara langsung: bagian yang Anda kutip berlaku untuk tabel sementara lokal dan global, batasan bernama adalah batasan yang Anda berikan nama secara sengaja, dan banyak pengguna berarti beberapa sesi.

Joe Obbish
sumber
11

Ini berlaku untuk tabel temp lokal.

Perbedaan antara kendala bernama dan tidak bernama adalah ini:

CREATE TABLE #t1 (c1 INT PRIMARY KEY CLUSTERED)

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

Membiarkan kendala nama sistem membuatnya sangat tidak mungkin terjadi tabrakan. Dalam contoh ini, jika Anda membuka dua jendela di SSMS, Anda bisa membuatnya #t1di keduanya, tetapi tidak #t2.

Tabel sementara global dibagikan oleh semua pengguna, jadi Anda harus menangani berbagai hal secara berbeda. Mereka tidak 'dihancurkan' sampai sesi terakhir selesai menggunakannya, jadi Anda perlu memastikan bahwa ketika pengguna mengaksesnya, mereka hanya dapat mengakses data mereka. Ini kadang-kadang dilakukan oleh SPID, kali lain dengan nilai hash. Itu tergantung pada bagaimana tabel temp global digunakan.

Biasanya untuk tabel temp global, prosedur tersimpan akan memeriksa untuk melihat apakah ada, dan kemudian hanya membuatnya jika OBJECT_ID()ada NULL.

Banyak pengguna berarti banyak sesi. Nama login tidak ada hubungannya dengan itu. Jika George berjalan sp_something @i = 1dan Gina berjalan sp_something @i = 2, tidak masalah jika keduanya masuk User1, mereka akan memiliki SPID yang berbeda.

Erik Darling
sumber