Rất nhiều người mới làm việc trên DB, vì vậy hãy đánh giá cao sự kiên nhẫn của bạn với một câu hỏi cơ bản. Tôi đang chạy SQL Server 2014 trên máy cục bộ của mình và tôi có một bảng nhỏ và ứng dụng khách cơ bản để kiểm tra các phương pháp khác nhau. Tôi nhận được những gì dường như là một khóa bảng trong cả hai INSERT INTO
và UPDATE
báo cáo. Máy khách là một ứng dụng ASP.NET có mã sau:
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();
Tôi chạy mã này, sau đó từ phòng quản lý tôi chạy SELECT * FROM LAYOUTSv2
. Trong cả hai trường hợp khi luồng máy khách bị tạm dừng (tức là trước khi xác nhận / rollback), truy vấn SELECT bị treo cho đến khi xảy ra cam kết / rollback.
Bảng có trường LAYOUTS_key được gán làm khóa chính. Trong cửa sổ thuộc tính, nó cho thấy nó là duy nhất và được nhóm, với khóa trang và khóa hàng đều được phép. Cài đặt leo thang khóa cho bảng là Vô hiệu hóa ... Tôi đã thử cả hai cài đặt có sẵn khác của Bảng và TỰ ĐỘNG mà không có thay đổi. Tôi đã thử SELECT ... WITH (NOLOCK)
và điều đó trả về một kết quả ngay lập tức, nhưng như được cảnh báo ở đây và những nơi khác, đó không phải là điều tôi nên làm. Tôi đã thử đưa ra ROWLOCK
gợi ý cho cả hai INSERT
và các UPDATE
tuyên bố, nhưng không có gì thay đổi.
Hành vi tôi đang tìm kiếm là: trước khi cam kết INSERT
, các truy vấn từ các luồng khác đọc tất cả các hàng ngoại trừ một hàng đang được chỉnh sửa INSERT
. Trước khi cam kết UPDATE
truy vấn từ các luồng khác, hãy đọc phiên bản bắt đầu của hàng đang được chỉnh sửa UPDATE
. Có cách nào tôi có thể làm điều này? Nếu tôi cần cung cấp thông tin khác để làm rõ trường hợp sử dụng của mình xin vui lòng cho tôi biết. Cảm ơn.
newkey
thành " something';DELETE FROM LAYOUTSv2 --
". Bản cập nhật của bạn sẽ hoàn tất thành công và sau đó làm trống bảng vì người dùng đã thao tác truy vấn bằng cách chèn dấu nháy đơn. Thông thường, một truy vấn được tham số hóa trông giống như UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
, sau đó bạn gán riêng (các) giá trị cho ?
(tham số) trong mã của bạn.
WHERE LAYOUTS_key='" + newkey + "'
là hoàn toàn không có vì nhiều lý do bao gồm cả SQL tiêm, bạn nên sử dụng các truy vấn được tham số hóa.