隔离级别
当锁定用作并发控制机制时,它可以解决并发问题。这使所有事务得以在彼此完全隔离的环境中运行,但是任何时候都可以有多个正在运行的事务。
可串行性是通过运行一组并发事务达到的数据库状态,等同于这组事务按某种顺序连续执行时所达到的数据库状态。
尽管可串行性对于事务确保数据库中的数据在所有时间内的正确性相当重要,然而许多事务并不总是要求完全的隔离。例如,多个作者工作于同一本书的不同章节。新章节可以在任意时候提交到项目中。但是,对于已经编辑过的章节,没有编辑人员的批准,作者不能对此章节进行任何更改。这样,尽管有未编辑的新章节,但编辑人员仍可以确保在任意时间该书籍项目的正确性。编辑人员可以查看以前编辑的章节以及最近提交的章节。
事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了 SQL Server 使用的锁定行为。
SQL-92 定义了下列四种隔离级别,SQL Server 支持所有这些隔离级别:
- 未提交读(事务隔离的最低级别,仅可保证不读取物理损坏的数据)。
- 提交读(SQL Server 默认级别)。
- 可重复读。
- 可串行读(事务隔离的最高级别,事务之间完全隔离)。
如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠事务均是串行的。
下面四种隔离级别允许不同类型的行为。
隔离级别 | 脏读 | 不可重复读取 | 幻像 |
---|---|---|---|
未提交读(Read UnCommited) | 是 | 是 | 是 |
提交读(Read Commited) | 否 | 是 | 是 |
可重复读(Repeatable Read) | 否 | 否 | 是 |
可串行读(Serialiazable) | 否 | 否 | 否 |
事务必须运行于可重复读或更高的隔离级别以防止丢失更新。当两个事务检索相同的行,然后基于原检索的值对行进行更新时,会发生丢失更新。如果两个事务使用一个 UPDATE 语句更新行,并且不基于以前检索的值进行更新,则在默认的提交读隔离级别不会发生丢失更新。
------------------------------------------------------
PS:以上摘自SQL Server联机文档
大部分关系数据库采用 提交读 的隔离级别,MySQL数据库采用 可重复读 的隔离级别
------------------------------------------------------
MySQL查询和修改隔离级别语句:
查询:select @@tx_isolation;
修改:set transation isolation level read uncommited;--//将数据库的隔离级别修改为 未提交读。
------------------------------------------------------
名词解释:
脏读:一个事务读到另一个事务,尚未提交的修改,就是脏读。这里所谓的修改,除了Update操作,不要忘了,还包括
Insert和Delete操作。脏读的后果:如果后一个事务回滚,那么它所做的修改,统统都会被撤销。前一个事务读到的数据,就是垃圾数据。
举个例子:预订房间。
有一张Reservation表,往表中插入一条记录,来订购一个房间。
事务1:在Reservation表中插入一条记录,用于预订99号房间。
事务2:查询,尚未预定的房间列表,因为99号房间,已经被事务1预订。所以不在列表中。
事务1:信用卡付款。由于付款失败,导致整个事务回滚。
所以插入到Reservation 表中的记录并不置为持久(即它将被删除)。
现在99号房间则为可用。
所以,事务2所用的是一个无效的房间列表,因为99号房间,已经可用。如果它是最后一个没有被预定的房间,那么这将是一个严重的失误。
注:脏读的后果很严重。
不可重复读:在同一个事务中,再次读取数据时【就是你的select操作】,所读取的数据,和第1次读取的数据,不一样了。就是不可重复读。如果,数据库系统的隔离级别。允许,不可重复读。那么你启动一个事务,并做一个select查询操作。查询到的数据,就有可能,和你第2次,3次...n次,查询到的数据不一样。一般情况下,你只会做一次,select查询,并以这一次的查询数据,作为后续计算的基础。因为允许出现,不可重复读。那么任何时候,查询到的数据,都有可能被其他事务更新,查询的结果将是不确定的。
举个例子:
事务1:查询有双人床房间。99号房间,有双人床。
事务2:将99号房间,改成单人床房间。
事务1:再次执行查询,请求所有双人床房间列表,99号房间不再列表中了。也就是说,
事务1,可以看到其他事务所做的修改。
在不可重复读,里面,可以看到其他事务所做的修改,而导致2次的查询结果不再一样了。
这里的修改,是提交过的。也可以是没有提交的,这种情况同时也是脏读。
幻读:事务1读取指定的where子句所返回的一些行。然后,事务2插入一个新行,这个新行也满足事务1使用的查询where子句。然后事务1再次使用相同的查询读取行,但是现在它看到了事务2刚插入的行。这个行被称为幻象,因为对事务1来说,这一行的出现是不可思议的。
举个例子:
事务1:请求没有预定的,双人床房间列表。
事务2:向Reservation表中插入一个新纪录,以预订99号房间,并提交。
事务1:再次请求有双人床的未预定的房间列表,99号房间,不再位于列表中。
注:幻读,针对的是,Insert操作。如果事务2,插入的记录,没有提交。那么同时也是脏读。