Sangat banyak pemula di pekerjaan DB, jadi menghargai kesabaran Anda dengan pertanyaan dasar. Saya menjalankan SQL Server 2014 pada mesin lokal saya, dan saya punya meja kecil dan aplikasi klien dasar untuk menguji berbagai pendekatan dengan. Saya mendapatkan apa yang tampaknya menjadi kunci tabel selama keduanya INSERT INTO
dan UPDATE
pernyataan. Klien adalah aplikasi ASP.NET dengan kode berikut:
OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();
Saya menjalankan kode ini, lalu dari studio manajemen yang saya jalankan SELECT * FROM LAYOUTSv2
. Selama kedua kasus ketika utas klien dijeda (yaitu sebelum komit / rollback) kueri SELECT hang sampai komit / rollback terjadi.
Tabel memiliki bidang LAYOUTS_key yang ditetapkan sebagai kunci utama. Di jendela properti itu menunjukkan bahwa itu unik dan berkerumun, dengan kunci halaman dan kunci baris keduanya diizinkan. Pengaturan eskalasi kunci untuk tabel adalah Nonaktifkan ... Saya sudah mencoba kedua pengaturan lain yang tersedia dari Tabel dan AUTO tanpa perubahan. Saya sudah mencoba SELECT ... WITH (NOLOCK)
dan itu mengembalikan hasilnya segera, tetapi seperti yang diperingatkan dengan baik di sini dan di tempat lain, bukan itu yang seharusnya saya lakukan. Saya sudah mencoba memberi ROWLOCK
petunjuk pada kedua pernyataan INSERT
dan UPDATE
, tetapi tidak ada yang berubah.
Perilaku yang saya cari adalah ini: sebelum melakukan suatu INSERT
, kueri dari utas lain membaca semua baris kecuali yang sedang INSERT
diedit. Sebelum melakukan UPDATE
kueri dari utas lain, baca versi awal dari baris yang sedang UPDATE
diedit. Apakah ada cara saya bisa melakukan ini? Jika saya perlu memberikan informasi lain untuk mengklarifikasi kasus penggunaan saya, beri tahu saya. Terima kasih.
newkey
ke " something';DELETE FROM LAYOUTSv2 --
". Pembaruan Anda akan selesai dengan sukses, dan kemudian mengosongkan tabel karena pengguna memanipulasi kueri dengan memasukkan tanda kutip. Biasanya, permintaan parameterisasi terlihat seperti UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
, setelah itu Anda secara terpisah memberikan nilai ke ?
(parameter) dalam kode Anda.
WHERE LAYOUTS_key='" + newkey + "'
adalah no-no lengkap untuk berbagai alasan termasuk injeksi SQL, Anda harus menggunakan query parameterised.