数据库工作非常新手,因此,感谢您对一个基本问题的耐心等待。我在本地计算机上运行SQL Server 2014,并且有一个小表和一个基本的客户端应用程序来测试不同的方法。我在INSERT INTO
和UPDATE
语句中都得到了一个表锁。客户端是具有以下代码的ASP.NET应用程序:
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();
我运行此代码,然后从Management Studio运行SELECT * FROM LAYOUTSv2
。在这两种情况下,当客户端线程暂停时(即,在提交/回滚之前),SELECT查询都将挂起,直到发生提交/回滚为止。
该表已将字段LAYOUTS_key分配为主键。在属性窗口中,它表明它是唯一的并且是集群的,同时允许页面锁和行锁。该表的锁定升级设置为“禁用” ...我尝试了表和AUTO的其他可用设置,而没有进行任何更改。我已经尝试过,SELECT ... WITH (NOLOCK)
并且会立即返回结果,但是正如此处和其他地方所警告的那样,这不是我应该做的。我尝试过ROWLOCK
在INSERT
和UPDATE
语句上都添加提示,但是没有任何变化。
我正在寻找的行为是这样的:在提交之前INSERT
,来自其他线程的查询会读取除INSERT
ed 之外的所有行。在UPDATE
从其他线程提交查询之前,请先阅读要UPDATE
编辑的行的起始版本。有什么办法可以做到吗?如果我需要提供其他信息来澄清用例,请告诉我。谢谢。
newkey
为“ something';DELETE FROM LAYOUTSv2 --
”。更新将成功完成,然后清空表,因为用户通过插入撇号来操纵查询。通常,参数化查询看起来像UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
,之后,您需要?
在代码中分别为(参数)分配值。
WHERE LAYOUTS_key='" + newkey + "'
出于各种原因(包括SQL注入),是完全禁止的,您应该使用参数化查询。