--可以显示的要求SQL Server使用行所 BEGIN TRAN DELETE FROM table1 WITH (rowlock) WHERE username='zhangsan' INSERT INTO table1 VALUES .... COMMIT TRAN --锁升级的前提是没有使用 WITH (rowlock) 提示.
另外,在Table上建立一个用户名栏位的索引可以避免使用表锁.这一招非常有效.
使用什么样的锁是由SQL SERVER根据性能的负载平衡来决定的,用户最好不要干涉。不过你可以通过优化你的代码来防止锁升级,行锁升级成页锁甚至表锁等。比如你在更新100万行数据时可以用下面的办法,避免锁升级:set rowcount 500 update_more: update [table] set A = ..... if @@rowcount > 0 goto update_more set rowcount 0
每个人的数据只涉及一行吗?那数据量怎么会很大呢,呵呵,难道有ntext,或者image类型的数据吗
--------------------------------------不是,每个人可能有上千行数据,数据都是普通的字符数据
同时有几千人操作。由于每个人操作并不影响其他人数据,
所以我想知道可不可以并行
如果可以,数据库会不会自动提升行锁为表锁
原因是:一个事物在修改数据时使用行级排它锁后,表依然会被加意向排它锁,意向排它锁依然会阻止另一个事务同时进行的修改数据提交,除非表上的意向排它锁被释放掉(也就是说前一个事物的行级排它锁被释放掉,这样该事物的修改数据已经提交)。所以用行级锁定SQL SERVER也不能允许两个用户各自的事务在同一时间修改表中的两行数据。
BEGIN TRAN
DELETE FROM table1 WITH (rowlock) WHERE username='zhangsan'
INSERT INTO table1 VALUES ....
COMMIT TRAN --锁升级的前提是没有使用 WITH (rowlock) 提示.
update_more:
update [table] set A = .....
if @@rowcount > 0
goto update_more
set rowcount 0
另外,我的操作是删除,然后插入。没有更新。
我知道的是,如果只是写的话,在2005里面,多个人应该可以同时写的。
只是删除时候呢?是不是能够只锁定需要删除的行?
为了描述清楚,我写些伪代码表UserId, UserInfo,
0001, 数据1
0001, 数据2
0002, 数据3
0003, 数据4
0002, 数据5
0001, 数据6
客户段代码private void 更新数据()
{
try{
开始事务;
执行("delete from 表名 with UserId="+UserId); insert="insert into 表名(UserId,UserInfo) values(@UserId, @UserInfo)";
for(int i=0;i<3000;i++){
para[“UserId”]=用户ID;
para[“UserInfo”]=用户信息;
执行;
} 提交事务;
}
catch(Exception ex){
回滚事务;
}
}
如果插入时,只涉及一行数据,没有什么好说的,因为执行时间很短。
我前面所说的数据修改的问题,用update举的例子,对删除行为一样适用。
在提交前,必须保持每个锁吧
还有前面删除的那些在提交前,也应该保持每个锁吧。
主要是使用了事务,那么在事务开始后,一直到事务提交或者回滚之前,是怎么加锁的?
————————————————————————————————————排它锁会一直保持到事务提交或回滚后才释放
--------------------------------------------------那就是说,一个用户在开始事务,进行数据操作,一直到事务提交或者回滚,别的用户都只能等待了??????????????
是的
-------------------------------------------------------------这是个不好的消息,如果每个用户插入数据需要5秒钟时间,那么6千人就需要3万秒,也就是500分钟,8个多小时!!!!!!!!!!!这绝对是不能忍受的。
——————————————————————————
为什么要这么做呢?难道被删除的和后来插入的行之间没有任何相关性吗?为什么不能去更新库中现有的行,再插入少量的数据就好了呢?如果一定要这么做的话,我觉得可以建两张表,一张是你现在操作的表(即主表),另一张是一张临时表,插入的时候先把数据放到临时表中,等业务空闲时,可以定期把临时表的数据导入到你的主表中(当然这需要系统自动完成),如果需要查询用户相关信息的时候,应该同时访问主表和临时表。
对于数据的删除,最好不要用delete语句去物理删除行,这样做性能不好(因为这会涉及到表索引的更新)。楼主可以在表上另建一列,用来表示行状态,删除的时候只需要更新这一列的状态值,标记这些行为无效就行了。同样的,可以等到业务空闲的时候再删除这些无效的行。如果一定要按照你说的方案,先物理删除,再物理插入,而且是从客户端多次向数据库提交insert来实现多行插入,那我也没有太好的性能优化的办法了。说到插入,你还可以尝试先把要插入的列,按照一定的格式写到一个文件中,然后从文件批量导入到SQL SERVER性能或许能高一些。另外,我觉得在你们的业务实现上,客户端做的事情有点太多了,其实应该尽量把大多数的业务放到SQL SERVER上来实现才能获得最好的性能。
所以业务只能在代码中实现,不能移到数据库里。既然这样,我想用户操作的等待,只能在程序中做了,考虑一下怎么安排这个队列。
最后,就是建议你操作的那张表上不要建聚集索引,也不要建立过多的非聚集索引,这样十分影响插入和删除的性能。
别的我也没有什么太好的建议了。