单条DML语句是否要加事务的讨论。

问题

------------------------------------------------

单条Update语句是否加事务与锁的关系
HI ALL,
  大家好,现在遇到了一点小疑惑。之前的SQLServer开发知识中讲到单条Update语句在SQLServer中按照隐式事务来处理的。我现在遇到这样一个问题,C#开发的多线程客户端联入SQLServer2005数据库,执行一个表的update 语句,Update的是单条记录。就是
update table set field=1 where 唯一ID=1这个样子。
在测试程序中,启动30个线程实例做系统压力测试,每个线程循环更新1000次表中的某一条记录,更新内容为一数值列+1操作。这时sp_lock观察数据库中的在线程执行过程中会产生大约20到30个锁的信息,锁的类型有Key、PAG、TAB。在全部测试线程执行结束后,锁会被自动释放掉。

如果在update语句中显式的写入Begin tran commit rollback tran后,通过sp_lock观察不到锁的信息。
请问,前一种情况是否可以判断为锁表,后一种则没有锁表。另外,隐式与显式事务的区别有这么大吗?期望专家指教!
问这个问题是由于在测试过程中发现了有锁导致系统异常的状况产生。


相关知识

------------------------------------------------

事务是SQL Server防止你的数据出现不一致状态的基础结构.

【显示事务】

显示事务是一种由你自己指定的事务.这种事务允许你自己决定哪批工作必须成功完成, 
否则所有部分都不完成.为了给自己的事务定界,可以使用关键字BEGIN TRANSACTION和 
ROLLBACK TRANSACTION或COMMIT TRANSACTION. 
BEGIN TRANSACTION—这个关键词用来通知SQL Server一个事务就要开始了. 
BEGIN TRANSACTION后面发生的每一条S Q L语句都是同一个事务中的一部分. 
ROLLBACK TRANSACTION—这个关键词用来通知SQL Server自BEGIN TRANSACTION 
后的所有工作都应取消,对数据库中任何数据的改变都被还原,任何已经创建或删除的对 
象被清除或恢复. 
COMMIT TRANSACTION—这个关键词用来通知SQL Server自BEGIN TRANSACTION 
后的全部工作都要完成并成为数据库的一个永久性部分.在同一个事务中,你不能同时 
使用ROLLBACK TRANSACTION和COMMIT TRANSACTION. 
你必须意识到,即使你的脚本中有错误,而你又让SQL Server提交事务,该事务也将执 
行.如果你打算依赖于现实事务保证数据完整性,必须在脚本中建立错误检查机制.

【隐式事务】

隐式事务是SQL Server为你而做的事务.隐式事务又称自动提交事务.如果运行一条 
I N S E RT语句,SQL Server将把它包装到事务中,如果此I N S E RT语句失败,SQL Server将回滚 
或取消这个事务.每条S Q L语句均被视为一个自身的事务.

讨论

------------------------------------------------

在单线程的程序中,隐式事务没有问题,但在多线程的程序中,应该使用显式事务,并指定事务的隔离等级。

有关这方面的资料可以参考Roy_88写的一篇关于死锁的文章;

SQL code ?
1
http://topic.csdn.net/u/20080721/20/15a60db6-34b5-4ea1-b392-11c42270aaab.html

事务的隔离等级
语法:
SET  TRANSACTION  ISOLATION  LEVEL
{READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SERIALIZABLE
}
1. READ UNCOMMITTED:完全没有隔离效果,读取到的数据随时都可能被别人更改事删除。
2. READ COMMITTED:不允许读取尚未COMMIT的数据。因为该数据被改动的几率很大。不过,在读取完数据后就和READ UNCOMMITTED一样,不会在乎该数据是否还会被别人更改。因此每次读取到的数据可能会不相同。
3. REPEATABLE READ:事务中所读取到的数据,将不允许别人更改或删除,以保证在事务中每次都可以读取到相同的内容。但别人仍然可以在该数据表中新增记录。
4. SERIALIZABLE:数据表全部锁定,不允许别人来修改、删除或新增数据。由于必须等到事务完成后,其他事务才能使用这些数据表,因此Serializable的并发性最低,要使用相同数据的事务必须一个个顺序地进行。


至于最开头的问题,解答如下:

第一种情况应该是C#多线程竞争时产生的自动锁吧。
对于插入和更新操作,原则上来说,如果存在多用户同时访问的情况,那么应当在SQL端用事务+事务隔离级来控制,防止出现同一操作出现不同结果的现象。清楼主多多注意这一点。另外,隐式的事务其实没有那么强的功能,只是更新和删除即时生效而已。

你可能感兴趣的:(MS,SQLSever(数据库))