
对于依赖于SQL的客户而言,如果不对同时使用数据库的用户数量进行检查,可能会对数据完整性造成严重的破坏。使用这些锁提示,你可以确保能够合理地处理数据修改。
在过去的几年中,SQL Server从一个小的办公数据存储逐渐发展为企业级的数据库服务器。用户同时访问数据库的数量也随着它的升级而递增。SQL Server 2000的锁资源标准似乎不是非常有效,但是,感谢上帝的是,它提供了可以重设标准锁的功能。锁提示可以告诉服务器该如何锁资源,但是在我们重设它们之前先来检查一下锁。
什么是锁
像SQL server一样的关系数据库使用锁来防止用户“互相踩到对方的脚趾头”。也就是说,锁可以防止用户造成修改数据时的碰撞。当一个用户锁住一段代码时候,其它的用户都不能修改这段数据。另外,一个锁阻止了用户观看未被授权的数据修改。用户必须等待到数据修改并保存之后才能够查看它。数据必须使用不同的方法来加锁。SQL
Server 2000使用锁来实现多用户同时修改数据库同一数据时的同步控制
死锁
一个数据库的死锁是发生在两个或多于两个访问一些资源的数据库会话中的,并且这些会话相互之间有依赖关系。死锁是可以在任意一个多线程的系统成出现的一个情况,不仅仅局限于关系数据库管理系统。一个多线程系统中的线程可能需要一个或多个资源(例如,锁)。如果申请的资源正在被另外一个线程所使用,那么第一个线程就需要等待持有该资源的线程的释放它所需要的资源。假设等待线程持有一个那个正拥有线程所依赖的资源。下面的这一段代码就可以造成死锁异常现象的发生:
System.Data.SqlClient.SqlException: Transaction (Process ID 12) was deadlocked
on lock resources with another process and has been chosen as the deadlock
victim. Rerun the transaction.
当一个SQL Server的调用和另外一个资源发生冲突时就会抛出异常,这个资源持有一个必要的资源。结果是,一个进程就被终止了。当进程的ID号成为系统的唯一标识的时候,这会是一个很平常死锁的消息错误。
锁的类型
一个数据库系统在许多情况下都有可能锁数据项。其可能性包括:
- Rows—数据库表中的一整行
- Pages—行的集合(通常为几kb)
- Extents—通常是几个页的集合
- Table—整个数据库表
- Database—被锁的整个数据库表
除非有其它的说明,数据库根据情况自己选择最好的锁方式。不过值得感谢的是,SQL
Server提供了一种避免默认行为的方法。这是由锁提示来完成的。
提示
或许你有过许多如下的经历:需要重设SQL Server的锁计划,并且加强数据库表中锁范围。Tansact-SQL提供了一系列不同级别的锁提示,你可以在SELECT,INSERT,UPDATE和DELETE中使用它们来告诉SQL Server你需要如何通过重设任何的系统或事务级别来锁表格。可以实现的提示包括:
- FASTFIRSTROW—选取结果集中的第一行,并将其优化
- HOLDLOCK—持有一个共享锁直至事务完成
- NOLOCK—不允许使用共享锁或独享锁。这可能会造成数据重写或者没有被确认就返回的情况;因此,就有可能使用到脏数据。这个提示只能在SELECT中使用。
- PAGLOCK—锁表格
- READCOMMITTED—只读取被事务确认的数据。这就是SQL Server的默认行为。
- READPAST—跳过被其它进程锁住的行,所以返回的数据可能会忽略行的内容。这也只能在SELECT中使用。
- READUNCOMMITTED—等价于NOLOCK.
- REPEATABLEREAD—在查询语句中,对所有数据使用锁。这可以防止其它的用户更新数据,但是新的行可能被其它的用户插入到数据中,并且被最新访问该数据的用户读取。
- ROWLOCK—按照行的级别来对数据上锁。SQL Server通常锁到页或者表级别来修改行,所以当开发者使用单行的时候,通常要重设这个设置。
- SERIALIZABLE—等价于HOLDLOCK.
- TABLOCK—按照表级别上锁。在运行多个有关表级别数据操作的时候,你可能需要使用到这个提示。
- UPDLOCK—当读取一个表的时候,使用更新锁来代替共享锁,并且保持一直拥有这个锁直至事务结束。它的好处是,可以允许你在阅读数据的时候可以不需要锁,并且以最快的速度更新数据。
- XLOCK—给所有的资源都上独享锁,直至事务结束。