现在用C#做一个程序,
程序有3步,
第一步,从数据库中读取数据
第二步,修改数据,由于修改计算比较复杂,存储过程不能完成,所以是用C#来完成的。
第三步,将数据写回数据库这这里面有个问题,就是多个用户同时修改数据时,容易混乱。
现在我的做法是,在表上增加一个字段Lock,每次读取数据前,判断Lock是否为0,如果是,设置为1,然后读取数据,交给C#计算,最后把计算结果写回数据库,再把Lock字段设置为0但我总觉得这种方法太苯了,请问各位前辈,MSSQL有提供这样类似的功能吗?如果有,该如何实施?先谢谢大家
程序有3步,
第一步,从数据库中读取数据
第二步,修改数据,由于修改计算比较复杂,存储过程不能完成,所以是用C#来完成的。
第三步,将数据写回数据库这这里面有个问题,就是多个用户同时修改数据时,容易混乱。
现在我的做法是,在表上增加一个字段Lock,每次读取数据前,判断Lock是否为0,如果是,设置为1,然后读取数据,交给C#计算,最后把计算结果写回数据库,再把Lock字段设置为0但我总觉得这种方法太苯了,请问各位前辈,MSSQL有提供这样类似的功能吗?如果有,该如何实施?先谢谢大家
1 如何锁一个表的某一行
/*
测试环境:windows 2K server + Mssql 2000
所有功能都进行测试过,并有相应的结果集,如果有什么疑义在论坛跟帖
关于版权的说明:部分资料来自互联网,如有不当请联系版主,版主会在第一时间处理。
功能:sql遍历文件夹下的文本文件名,当然你修改部分代码后可以完成各种文件的列表。
*/
A 连接中执行SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transelect * from tablename with (rowlock) where id=3waitfor delay '00:00:05'commit tranB连接中如果执行update tablename set colname='10' where id=3 --则要等待5秒update tablename set colname='10' where id <>3 --可立即执行2 锁定数据库的一个表SELECT * FROM table WITH (HOLDLOCK)
注意: 锁定数据库的一个表的区别SELECT * FROM table WITH (HOLDLOCK)
其他事务可以读取表,但不能更新删除SELECT * FROM table WITH (TABLOCKX)
其他事务不能读取表,更新和删除加with (rowlock)
现在计算的程序写了有1000多行了,不可能再用存储过程完成的。C#里的List<T>等对象,也不是存储过程可以取代的。
难到没有办法了吗?
第一步,从数据库中读取数据 --在此处加锁,SELECT完毕后,锁就自动释放了第二步,修改数据,由于修改计算比较复杂,存储过程不能完成,所以是用C#来完成的。 --上面锁释放了,可是这里的运算才刚刚开始,请注意,计算是在C#里,不在MSSQL中第三步,将数据写回数据库
第一步,从数据库中读取数据 --在此处加锁,SELECT完毕后,锁就自动释放了
我想问问,第一步完成,事务是否已经结束了?
---\\\\
NO
DataBase.Open() //读出数据
ArrayList tList=DataBase.read("SELECT LineA,LineB,LineC,LineD FROM Table")
//这里是大量的计算
for(int i=0;i<tList.Count;i++){
//....
} //把数据写回去
DataBase.Update("Update Table SET LineA=@LineA,LineB=@LineB,LineC=@LineC,LineD=@LineD",tList)
}请问楼上,事务是在 SELECT时开始,在Update时结束吗?
我认为2楼方法不适用.这个必须在读数据时就加排它锁xlock,配置paglock,不能配置rowlock.像楼主12楼的写法,需要改成事务提交的方式,不知道楼主有没有这方面的基类可以调用.
select * from tb with(xlock,paglock) where id=3\
--直到这个事务结束,也就是commit tran 或是rollback tran ,其它用户才能读取到id=3的这条记录.
commit tranrowlock在mssql里,很难使用,因为行级锁对于sql server来讲,需要更高的代价来控制
由于很多数据行存在于一个数据页内,锁数据页要比锁行代价低
而且如果更新多条数据都存在于一个数据页,那么如果使用行级锁,极有可能会造成多个用户行锁定方向不同而产生锁死
而锁页,这种情况就会减少.
嗯,只能改程序,配置连接事务SqlTransaction myTransaction = myConn.BeginTransaction();
使用paglock,页锁,这样只锁定数据行所在的一页,其它的数据页还可以读取.tablock就不好了.
呵呵,难道完美也用.net?加字段+事务解决吧,我感觉这个不错,
而且查询和更新字段的时候注意加上排它锁,禁止
其他连接读出数据,这样就能保证只有你一个人操作数据了
昨晚也去google了解一下,的确只有SqlTransaction myTransaction = myConn.BeginTransaction();才可解决问题
事务对象有隔离方式的属性Chaos 无法改写隔离级别更高的事务中的挂起的更改。
ReadCommitted 在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。
ReadUncommitted 可以进行脏读,意思是说,不发布共享锁,也不接受独占锁。
RepeatableRead 在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。防止不可重复的读取,但是仍可以有幻像行。
Serializable 在DataSet上放置范围锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行。
Unspecified 正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。 象我这样的程序,用那种比较好呢?
就是这样子.select 时用with(xlock,paglock).
如果相等,就说明从读取到写入数据库,就没有别人修改过,可以修改,
否则就不能修改,在写入的时候被别的用户修改过了,提示一个错误!
update tt from col=,upd_date=getdate()
where upd_date=@t
pageLock表示“锁页”我想用TableLock是否更加安全?谢谢,结帖