mysql,oracle,sql server中的默认事务隔离级别查看,更改 And SQLserver锁和事务隔离级别的比较与使用

未提交读(隔离事务的最低级别,只能保证不读取物理上损坏的数据)

已提交读(数据库引擎的默认级别)

可重复读

可序列化(隔离事务的最高级别,事务之间完全隔离)

 

可串行化比较严谨,级别高;

MySQL

mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读

1.查看当前会话隔离级别

select @@tx_isolation;

2.查看系统当前隔离级别

select @@global.tx_isolation;

3.设置当前会话隔离级别

set session transaction isolatin level repeatable read;

4.设置系统当前隔离级别

set global transaction isolation level repeatable read;

Oracle

oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。

默认系统事务隔离级别是READ COMMITTED,也就是读已提交

1.查看系统默认事务隔离级别,也是当前会话隔离级别

--首先创建一个事务
declare
     trans_id Varchar2(100);
  begin
     trans_id := dbms_transaction.local_transaction_id( TRUE );
  end; 

--查看事务隔离级别

SELECT s.sid, s.serial#,

  CASE BITAND(t.flag, POWER(2, 28))
    WHEN 0 THEN 'READ COMMITTED'
    ELSE 'SERIALIZABLE'
  END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');

SQL Server

默认系统事务隔离级别是read committed,也就是读已提交

1.查看系统当前隔离级别

DBCC USEROPTIONS 

isolation level 这一项的 Value 既是当前的隔离级别设置值

2.设置系统当前隔离级别

SET TRANSACTION ISOLATION LEVEL Read UnCommitted;

其中Read UnCommitted为需要设置的值

 

------------------------------------------------------------------------------------------

SQLserver锁和事务隔离级别的比较与使用

 

对象

①     :每条SQL语句

②     隔离:事务

并发问题

丢失更新

未确认的读取(脏读)

不一致的分析(非重复读):多次读取相同的数据(行)不一致(其他用户更改update)

幻像读:多次读取有不存在和新增的数据(其他用户插入insert或删除delete)

隔离级别

隔离级别

脏读

不可重复读取

幻像

说明

未提交读(read uncommitted)

如果其他事务更新,不管是否提交,立即执行

提交读(read committed默认)

读取提交过的数据。如果其他事务更新没提交,则等待

可重复读(repeatable read)

查询期间,不允许其他事务update

可串行读(serializable)

查询期间,不允许其他事务insert或delete

提交读

假设存在表A,如下所示

A1

A2

A3

11

21

31

12

22

32

打开查询分析器并打开两个连接,分别输入如下两个事务:

 

--事务Ⅰ

SET TRANSACTION ISOLATION LEVEL READ Committed

begin tran

update A set A2 = 20 where A1 = 11

waitfor delay '00:00:10'

rollback tran

--事务Ⅱ

SET TRANSACTION ISOLATION LEVEL READ Committed

select * from A where A1 = 11

 

如果先运行事务Ⅰ,然后紧接着运行事务Ⅱ,则事务Ⅱ要等待10秒钟(一个连接在修改数据块时别的连接也不能查询这个数据块,直到解。反之亦然:读的时候不能写和修改)。

如果把事务Ⅱ改为如下

SET TRANSACTION ISOLATION LEVEL READ UNCommitted

select * from A where A1 = 11

那么事务Ⅱ不需等待,立即执行(可以看出READ UNCommitted事务select不对数据发出共享

:(这里主要讲解 共享 和 排他 两种经常用到的)

共享主要是为了共享读(select),如果存在事务(一个或多个)拥有对表中数据(关于数据的多少,视的粒度而定)的共享,不允许对定的数据进行更新(update)(从的角度讲,即不允许事务获取排他,要等到所有的共享都释放掉)。反之,如果事务对数据已经具有排他(只能有一个),其他的事务就不能对定的数据获取共享和排他(即排他与共享不能兼容,更多信息请查看兼容性),在此特别强调一下 定的数据 ,因为有的资料上讲解到“一个连接写的时候,另一个连接可以写”,实际上写的这种情况是各个连接的读写的数据不是相同的行,也就是说各个连接定的数据不同。

根据以上分析,我们总结为六个字为“共享读,排他写”。

了解了的情况之后,又涉及到一个问题。事务究竟要保持多久呢?

一般来说,共享定时间与事务的隔离级别有关,如果隔离级别为Read Committed的默认级别,只在读取(select)的期间保持定,即在查询出数据以后就释放了;如果隔离级别为更高的Repeatable read或Serializable,直到事务结束才释放。另说明,如果select语句中指定了HoldLock提示,则也要等到事务结束才释放

排他直到事务结束才释放。

做出了以上分析,现在我们可能会存在这样的疑问,到底在执行SQL语句的时候发出什么样的呢,这就由事务的隔离级别决定了。一般情况,读语句(select)发出共享,写语句(update,insert,delete)发出排他。但是,如果这样不能满足我们的要求怎么办呢,有没有更多选择呢,别急,SQLserver为我们提供了定提示的概念。

       定提示对SQL语句进行特别指定,这个指定将覆盖事务的隔离级别。下面对各个定提示分别予以介绍(更多资料请查看SQLserver的联机帮助),笔者做出了以下分类。

类型1

①     READUNCOMMITTED:不发出

②     READCOMMITTED:发出共享,保持到读取结束

③     REPEATABLEREAD:发出共享,保持到事务结束

④     SERIALIZABLE:发出共享,保持到事务结束

类型2

①     NOLOCK:不发出。等同于READUNCOMMITTED

②     HOLDLOCK:发出共享,保持到事务结束。等同于SERIALIZABLE

③     XLOCK:发出排他,保持到事务结束。

④     UPDLOCK:发出更新,保持到事务事务结束。(更新:不阻塞别的事物,允许别的事物读数据(即更新可与共享兼容),但他确保自上次读取数据后数据没有被更新)

⑤     READPAST:发出共享,但跳过定行,它不会被阻塞。适用条件:提交读的隔离级别,行级,select语句中。

类型3

①     ROWLOCK:行级

②     PAGLOCK:页级

③     TABLOCK:表

④     TABLOCKX:表排他

讲解完后,下面结合一个具体实例,具体看一下的使用。

       在很多系统中,经常会遇到这种情况,要保持一个编号的唯一,如会计软件中的凭证的编号。一种编号的处理是这样的,把表中的最大编号保存到表中,然后在这个编号上累加,形成新的编号。这个过程对并发处理要求非常高,下面我们就来模拟这个过程,看如何保持编号的唯一性。

       新建一张表code来保存凭证的最大编号。字段如下:编号:bh(numeric(18,0)),凭证表名pinzheng(varchar(50))

假设表中有这样的一条记录:

 

Bh

Pinzheng

18000

会计凭证

 

新建一个存储过程来生成新的凭证编号,如下:

CREATE PROCEDURE up_getbh  AS

       Begin Tran

              Declare @numnewbh numeric(18,0)

              select  @numnewbh = bh FROM code  WITH (UPDLOCK,ROWLOCK) where pinzheng = '会计凭证'

              set @numnewbh = @numnewbh + 1

              update code set  bh = @numnewbh where pinzheng = '会计凭证'

              print @numnewbh

       Commit tran

GO

 

然后,打开查询分析器,并多开几个连接(笔者开了8个连接,模拟有8个人同时并发,读者可以开更多的连接进行试验),把类似以下这样的语句复制到每个连接窗口中,

declare @i numeric(18,0)

set @i = 1

while @i = 1

Begin

       if getdate() > '2004-07-22 14:23'  --设定一个时间,到此时间同时执行upgetbh存储过程

              set @i = 0      

end

exec up_getbh

 

然后,接连运行各个连接,到2004-7-22 14:23 这一刻,各个连接同时运行up_getbh。从运行结果可以看出连接顺序出现18001开始个数字,并没有重号或丢号的现象。

 

分析:由于up_getbh中的select语句使用了更新,因更新之间不能兼容,所以各个连接要等到所有其他的连接释放掉才能执行,而更新的释放要等到事务结束,这样就不会发生号出错的现象了。

 

附:的兼容性表

现有的授权模式

人生无处不PK

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值