MSSQL事务开发指南    

了解事务
事务是作为单个逻辑工作单元执行的一系列操作。可以是一条SQL语句也可以是多条SQL语句。
事务具有四个特性
原子性:不可分隔、成则具成、败则具败。
一致性:事务在完成时,必须使所有的数据都保持一致状态
隔离性:独立的执行互不干扰。由并发事务所作的修改必须与任何其他并发事务所作的修改隔离。
持久性:务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。
应用程序主要通过指定事务启动和结束的时间来控制事务。
启动事务:使用 API 函数和 Transact-SQL 语句,可以按显式、自动提交或隐式的方式来启动事务。
结束事务:您可以使用 COMMIT(成功) 或 ROLLBACK(失败) 语句,或者通过 API 函数来结束事务。
事务模式分为:显示事务模式、隐式事务模式、自动事务模式。在SQL常用的是显示模式。
事务并发处理会产生的问题:
1,丢失更新
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。
每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。
2,脏读
当第二个事务选择其它事务正在更新的行时,会发生未确认的相关性问题。
第二个事务正在读取的数据还没有确认并且可能由更新此行的事务所更改。
3,不可重复读
当第二个事务多次访问同一行而且每次读取不同的数据时,会发生不一致的分析问题。
不一致的分析与未确认的相关性类似,因为其它事务也是正在更改第二个事务正在读取的数据。
然而,在不一致的分析中,第二个事务读取的数据是由已进行了更改的事务提交的。而且,不一致的分析涉及多次(两次或更多)读取同一行,而且每次信息都由其它事务更改;因而该行被非重复读取。
4,幻像读
当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。
事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。
事务的隔离级别
该隔离级别定义一个事务必须与其他事务所进行的资源或数据更改相隔离的程度。事务隔离级别控制:
读取数据时是否占用锁以及所请求的锁类型。
占用读取锁的时间。
引用其他事务修改的行的读取操作是否:
在该行上的排他锁被释放之前阻塞其他事务。
检索在启动语句或事务时存在的行的已提交版本。
读取未提交的数据修改。
事务的隔离级别
SQL语句可以使用SET TRANSACTION ISOLATION LEVEL来设置事务的隔离级别。
1. Read Uncommitted:最低等级的事务隔离,仅仅保证了读取过程中不会读取到非法数据。上诉4种不确定情况均有可能发生。
2. Read Committed:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
第一个查询事务
SET TRANSACTION ISOLATION LEVEL Read Committed
begin tran
update Cate SET Sname=Sname+'b' where ID=1
SELECT * FROM cate where ID=1
waitfor delay '00:00:6'
rollback tran --回滚事务
select Getdate()
SELECT * FROM cate where ID=1
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed --把committed换成Read uncommitted可看到“脏读取”的示例。
SELECT * FROM cate where ID=1
select Getdate()
可以看到使用 Read Committed 成功的避免了“脏读取”.
3. Repeatable Read:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
第一个查询事务
SET TRANSACTION ISOLATION LEVEL Repeatable Read -- 把Repeatable Read换成Read committed可以看到“不可重复读取”的示例
begin tran
SELECT * FROM cate where ID=33 --第一次读取数据
waitfor delay '00:00:6'
SELECT * FROM cate where ID=33 --第二次读取数据,不可重复读取
commit
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed
update cate set Sname=Sname+'JD' where ID=33
SELECT * FROM cate where ID>30
4. Serializable:最高等级的事务隔离,上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。
在第一个查询窗口执行
SET TRANSACTION ISOLATION LEVEL Serializable -- 把Serializable换成Repeatable Read 可看到“幻像读”的示例
begin tran
SELECT * FROM cate where ID>30 --第一次读取数据,“幻像读”的示例
waitfor delay '00:00:6' --延迟6秒读取
SELECT * FROM cate where ID>30 --第一次读取数据
commit
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed
Delete from cate where ID>33
SELECT * FROM cate where ID>30
创建事务

设置事务级别:SET TRANSACTION ISOLATION LEVEL
开始事务:begin tran
提交事务:COMMIT
回滚事务:ROLLBACK
创建事务保存点:SAVE TRANSACTION savepoint_name
回滚到事务点:ROLLBACK TRANSACTION savepoint_name

创建事务的原则:
尽可能使事务保持简短很重要,当事务启动后,数据库管理系统 (DBMS) 必须在事务结束之前保留很多资源、以保证事务的正确安全执行。
特别是在大量并发的系统中, 保持事务简短以减少并发 资源锁定争夺,将先得更为重要。
1、事务处理,禁止与用户交互,在事务开始前完成用户输入。
2、在浏览数据时,尽量不要打开事务
3、尽可能使事务保持简短。
4、考虑为只读查询使用快照隔离,以减少阻塞。
5、灵活地使用更低的事务隔离级别。
6、灵活地使用更低的游标并发选项,例如开放式并发选项。
7、在事务中尽量使访问的数据量最小。

关联文档