给你这些例子,看后会有收获的:)---------------------- --建立测试表的语句 CREATE TABLE 帐户表 ( 帐号 CHAR(4), 余额 INT ) GO INSERT 帐户表 SELECT 'A',100 UNION ALL SELECT 'B',2001、排它锁测试--在第一个连接中执行以下语句 BEGIN TRAN UPDATE 帐户表 SET 余额=300 WHERE 帐号='A' WAITFOR DELAY '00:00:10' --等待10秒 COMMIT TRAN--在第二个连接中执行以下语句 BEGIN TRAN SELECT * FROM 帐户表 WHERE 帐号<>'A' COMMIT TRAN/**说明: 若同时执行上述两个语句,只要第一句更新的行数大于零,则第二句必须等待10秒。 疑问:如果帐户A的余额本来就是300,第二个连接也会立即返回 如果连接二中把SELECT * FROM 帐户表 改成 SELECT * FROM 帐户表 WITH ( NOLOCK),读取任何记录,都不需要等待 或者在连接二使用READ UNCOMMITTED隔离级别也可执行语句一时,系统会在帐户表上使用TABLOCKX排它锁。该锁可以防止其它事务读取或更新表,并在语句或事务结束前一直持有。 NOLOCK选项:该选项不发出共享锁,并且不要提供排它锁。当此选项生效时,可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅应用于 SELECT 语句。 **/ 2、 --在第一个连接中执行以下语句 BEGIN TRAN SELECT * FROM 帐户表 WHERE 帐号='A' WAITFOR DELAY '00:00:10' COMMIT TRAN--在第二个连接中执行以下语句 --A句 UPDATE 帐户表 SET 余额=10 WHERE 帐号='A' --要等待10秒,从而避免非重复读 --B句 UPDATE 帐户表 SET 余额=10 WHERE 帐号='B' --不需要等待,立即执行--如果想在连接一中锁住整个表,不允许其他事务更新表中任何记录,但可以读取记录,可使用HOLDLOCK选项,即(HOLDLOCK 等同于 SERIALIZABLE) BEGIN TRAN SELECT * FROM 帐户表 WITH(HOLDLOCK) WHERE 帐号='A' WAITFOR DELAY '00:00:10' COMMIT TRAN--如果想在连接一中锁住整个表,不允许其他事务更新表中任何记录甚至读取表中任何记录,可使用TABLOCKX选项,即(SET TRANSACTION ISOLATION LEVEL SERIALIZABLE做不到) BEGIN TRAN SELECT * FROM 帐户表 WITH(TABLOCKX) WHERE 帐号='A' WAITFOR DELAY '00:00:10' COMMIT TRAN --如果想在连接一中不锁定表,允许其他事务更新表中任何行,使用NOLOCK选项,即 BEGIN TRAN SELECT * FROM 帐户表 WITH(NOLOCK) WHERE 帐号='A' WAITFOR DELAY '00:00:10' COMMIT TRAN SET TRANSACTION ISOLATION LEVEL REPEATABLE READ BEGIN TRAN SELECT * FROM 帐户表 WITH (ROWLOCK) WHERE 帐号='A' WAITFOR DELAY '00:00:10' COMMIT TRAN3、死锁测试 --增设 帐户表_2 CREATE TABLE 帐户表_2 ( 帐号 CHAR(4), 余额 INT ) GO INSERT 帐户表_2 SELECT 'C',100 UNION ALL SELECT 'D',200 --在第一个连接中执行以下语句 BEGIN TRAN UPDATE 帐户表 SET 余额=3 WHERE 帐号='A' WAITFOR DELAY '00:00:10' UPDATE 帐户表_2 SET 余额=3 WHERE 帐号='C' COMMIT TRAN
--在第二个连接中执行以下语句 BEGIN TRAN UPDATE 帐户表_2 SET 余额=4 WHERE 帐号='C' WAITFOR DELAY '00:00:10' UPDATE 帐户表 SET 余额=4 WHERE 帐号='A' COMMIT TRAN--删除测试表 DROP TABLE 帐户表,帐户表_2--同时执行,系统会检测出死锁,第一个连接的事务可能正常执行,SQL Server 终止第二个连接的事务(不涉及超时)。 --如果没有出现死锁,则在其它事务释放锁之前,请求锁的事务被阻塞。 --LOCK_TIMEOUT 设置允许应用程序设置语句等待阻塞资源的最长时间。4、更新数据时候允许进行插入 5、插入数据时不允许更新\读取
--建立测试表的语句
CREATE TABLE 帐户表
(
帐号 CHAR(4),
余额 INT
)
GO
INSERT 帐户表
SELECT 'A',100
UNION ALL
SELECT 'B',2001、排它锁测试--在第一个连接中执行以下语句
BEGIN TRAN
UPDATE 帐户表 SET 余额=300 WHERE 帐号='A'
WAITFOR DELAY '00:00:10' --等待10秒
COMMIT TRAN--在第二个连接中执行以下语句
BEGIN TRAN
SELECT * FROM 帐户表 WHERE 帐号<>'A'
COMMIT TRAN/**说明:
若同时执行上述两个语句,只要第一句更新的行数大于零,则第二句必须等待10秒。
疑问:如果帐户A的余额本来就是300,第二个连接也会立即返回
如果连接二中把SELECT * FROM 帐户表 改成 SELECT * FROM 帐户表 WITH ( NOLOCK),读取任何记录,都不需要等待
或者在连接二使用READ UNCOMMITTED隔离级别也可执行语句一时,系统会在帐户表上使用TABLOCKX排它锁。该锁可以防止其它事务读取或更新表,并在语句或事务结束前一直持有。
NOLOCK选项:该选项不发出共享锁,并且不要提供排它锁。当此选项生效时,可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅应用于 SELECT 语句。
**/
2、
--在第一个连接中执行以下语句
BEGIN TRAN
SELECT * FROM 帐户表 WHERE 帐号='A'
WAITFOR DELAY '00:00:10'
COMMIT TRAN--在第二个连接中执行以下语句
--A句
UPDATE 帐户表 SET 余额=10 WHERE 帐号='A' --要等待10秒,从而避免非重复读
--B句
UPDATE 帐户表 SET 余额=10 WHERE 帐号='B' --不需要等待,立即执行--如果想在连接一中锁住整个表,不允许其他事务更新表中任何记录,但可以读取记录,可使用HOLDLOCK选项,即(HOLDLOCK 等同于 SERIALIZABLE)
BEGIN TRAN
SELECT * FROM 帐户表 WITH(HOLDLOCK) WHERE 帐号='A'
WAITFOR DELAY '00:00:10'
COMMIT TRAN--如果想在连接一中锁住整个表,不允许其他事务更新表中任何记录甚至读取表中任何记录,可使用TABLOCKX选项,即(SET TRANSACTION ISOLATION LEVEL SERIALIZABLE做不到)
BEGIN TRAN
SELECT * FROM 帐户表 WITH(TABLOCKX) WHERE 帐号='A'
WAITFOR DELAY '00:00:10'
COMMIT TRAN
--如果想在连接一中不锁定表,允许其他事务更新表中任何行,使用NOLOCK选项,即
BEGIN TRAN
SELECT * FROM 帐户表 WITH(NOLOCK) WHERE 帐号='A'
WAITFOR DELAY '00:00:10'
COMMIT TRAN
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRAN
SELECT * FROM 帐户表 WITH (ROWLOCK) WHERE 帐号='A'
WAITFOR DELAY '00:00:10'
COMMIT TRAN3、死锁测试
--增设 帐户表_2
CREATE TABLE 帐户表_2
(
帐号 CHAR(4),
余额 INT
)
GO
INSERT 帐户表_2
SELECT 'C',100
UNION ALL
SELECT 'D',200
--在第一个连接中执行以下语句
BEGIN TRAN
UPDATE 帐户表 SET 余额=3 WHERE 帐号='A'
WAITFOR DELAY '00:00:10'
UPDATE 帐户表_2 SET 余额=3 WHERE 帐号='C'
COMMIT TRAN
--在第二个连接中执行以下语句
BEGIN TRAN
UPDATE 帐户表_2 SET 余额=4 WHERE 帐号='C'
WAITFOR DELAY '00:00:10'
UPDATE 帐户表 SET 余额=4 WHERE 帐号='A'
COMMIT TRAN--删除测试表
DROP TABLE 帐户表,帐户表_2--同时执行,系统会检测出死锁,第一个连接的事务可能正常执行,SQL Server 终止第二个连接的事务(不涉及超时)。
--如果没有出现死锁,则在其它事务释放锁之前,请求锁的事务被阻塞。
--LOCK_TIMEOUT 设置允许应用程序设置语句等待阻塞资源的最长时间。4、更新数据时候允许进行插入
5、插入数据时不允许更新\读取