日期:2014-01-03  浏览次数:20634 次

Sqlserver2000中的并发问题一、并发问题的产生:
如果没有锁定且多个用户同时访问一个数据库,则当他们的事务同时使用相反的数据时可能会发生问题。并发问题包括:
丢失或覆盖更新。未确认的相关性(脏读)。不分歧的分析(非反复读)。幻像读。 1、丢失更新:当两个或多个事务选择同一行,然后基于最后选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新将重写由其它事务所做的更新,这将导致数据丢失。
例如,两个编辑人员制造了同一文档的电子复本。每个编辑人员独立地更改其复本,然后保存更改后的复本,这样就覆盖了原始文档。最后保存其更改复本的编辑人员覆盖了第一个编辑人员所做的更改。如果在第一个编辑人员完成之后第二个编辑人员才能进行更改,则可以避免该问题。
2、未确认的相关性(脏读)
当第二个事务选择其它事务正在更新的行时,会发生未确认的相关性问题。第二个事务正在读取的数据还没有确认并且可能由更新此行的事务所更改。

例如,一个编辑人员正在更改电子文档。在更改过程中,另一个编辑人员复制了该文档(该复本包含到目前为止所做的全部更改)并将其分发给预期的用户。此后,第一个编辑人员认为目前所做的更改是错误的,于是删除了所做的编辑并保存了文档。分发给用户的文档包含不再存在的编辑内容,并且这些编辑内容应认为从未存在过。如果在第一个编辑人员确定最终更改前任何人都不能读取更改的文档,则可以避免该问题。
3、不分歧的分析(非反复读)
当第二个事务多次访问同一行而且每次读取不同的数据时,会发生不分歧的分析问题。不分歧的分析与未确认的相关性类似,由于其它事务也是正在更改第二个事务正在读取的数据。然而,在不分歧的分析中,第二个事务读取的数据是由已进行了更改的事务提交的。而且,不分歧的分析涉及多次(两次或更多)读取同一行,而且每次信息都由其它事务更改;因此该行被非反复读取。

例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可反复。如果只要在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
4、幻像读
当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,由于该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。

例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
二、并发问题的处理方案:
当锁定用作并发控制机制时,它可以处理并发问题。这使所有事务得以在彼此完全隔离的环境中运转,但是任何时候都可以有多个正在运转的事务。

可串行性是通过运转一组并发事务达到的数据库形状,等同于这组事务按某种顺序连续执行时所达到的数据库形状。
SQL-92 隔离级别
虽然可串行性对于事务确保数据库中的数据在所有时间内的正确性相当重要,然而许多事务并不总是要求完全的隔离。例如,多个作者任务于同一本书的不同章节。新章节可以在任意时候提交到项目中。但是,对于曾经编辑过的章节,没有编辑人员的批准,作者不能对此章节进行任何更改。这样,虽然有未编辑的新章节,但编辑人员仍可以确保在任意时间该书籍项目的正确性。编辑人员可以查看以前编辑的章节以及最近提交的章节。

事务预备接受不分歧数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以添加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。使用程序要求的隔离级别确定了 SQL Server 使用的锁定行为。

SQL-92 定义了下列四种隔离级别,SQL Server 支持所有这些隔离级别:
未提交读(事务隔离的最低级别,仅可保证不读取物理损坏的数据)。提交读(SQL Server 默认级别)。可反复读。可串行读(事务隔离的最高级别,事务之间完全隔离)。
如果事务在可串行读隔离级别上运转,则可以保证任何并发堆叠事务均是串行的。

下面四种隔离级别允许不同类型的行为。

隔离级别

脏读

不可反复读取

幻像

 

 

未提交读







提交读







可反复读







可串行读







 

事务必须运转于可反复读或更高的隔离级别以防止丢失更新。当两个事务检索相反的行,然后基于原检索的值对行进行更新时,会发生丢失更新。如果两个事务使用一个 UPDATE 语句更新行,并且不基于以前检索的值进行更新,则在默认的提交读隔离级别不会发生丢失更新。

三、问题处理的实现:
1、       默认处理方案:SET TRANSACTION ISOLATION LEVEL
控制由连接发出的所有 Microsoft® SQL Server™ SELECT 语句的默认事务锁定行为。
语法
SET TRANSACTION ISOLATION LEVEL
    { READ COMMITTED
        | READ UNCOMMITTED
        | REPEATABLE READ
        | SERIALIZABLE
    }
参数
READ COMMITTED

指定在读取数据时控制共享锁以避免脏读,但数据可在事务结束前更改,从而产生不可反复读取或幻像数据。该选项是 SQL Server 的默认值。

READ UNCOMMITTED

执行脏读或 0 级隔离锁定,这表示不发出共享锁,也不接受排它锁。当设置该选项时,可以对数据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出如今数据集中或从数据集消逝。该选项的作用与在事务内所有语句中的所有表上设置 NOLOCK 相反。这是四个隔离级别中限制最小的级别。

REPEATABLE READ

锁定查询中使用的所无数据以防止其他用户更新数据,但是其他用户可以将新的幻像行插入数据集,且幻像行包括在当前事务的后续读取中。由于并发低于默认隔离级别,所以应只在必要时才使用该选项。

SERIALIZABLE

在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。这是四个隔离级别中限制最大的级别。由于并发级别较低,所以应只在必要时才使用该选项。该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 HOLDLOCK 相反。
注释
一次只能设置这些选项中的一个,而且设置的选项将不断对那个连接保持无效,直到显式更改该选项为止。这是默认行为,除非在语句的 FROM 子句中在表级上指定优化选项。

SET TRANSACTION ISOLATION LEVEL 的设置是在执行或运转时设置,而不是在分析时设置。
示例
下例为会话设置 TRANSACTION ISOLATION LEVEL。对于每个后续 Transact-SQL 语句,SQL Server 将所有共享锁不断控制到事务结束为止。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

GO

BEGIN TRANSACTION

SELECT * FROM publishers

SELECT * FROM authors

...

COMMIT TRANSACTION
2、自定义事务隔离级别
默认情况下,Microsoft® SQL Server™ 2000 在 READ COMMITTED 的一个隔离级别上操作。但是,使用程序可能