GBase 8s
其他
文章

南大通用GBase8sV8.8隔离级别的介绍

发表于2026-08-05 17:50:46327次浏览1个评论

在高并发的数据库生产环境中,多个事务同时读写数据时,如何平衡数据一致性与系统并发性能,是每个DBA和开发者都必须面对的核心问题。GBase 8s V8.8 提供了丰富的隔离级别机制,让我们能够根据业务场景灵活控制事务间的可见性与锁行为。

本文将系统梳理GBase 8s支持的五种隔离级别,从原理、优缺点到双会话实验示例,带你彻底搞懂脏读、不可重复读、幻读等经典问题在GBase 8s中的表现,并给出生产环境的选型建议。

一、隔离级别概述

多个同时运行的事物之间不会互相影响彼此的执行
每个用户感觉自己的事务都是排他的执行
同时发生的其他事务应该出现在当前事务的前或者后
类似一个事务中的“序列”

1.脏读


设置方式:SET ISOLATION TO DIRTY READ;

  • 采用这种隔离级别,数据库服务器不会分配任何锁
  • 查询过程中,可以查询到任何数据row, 甚至那些被修改但尚未提交的记录
  • Dirty-read隔离级别将产生幻影读,不可重复读的问题
  • 非日志数据库中只有Dirty-read一种隔离级别
  • Dirty-read 隔离级别应用场景

    静态表 (no updates, read-only tables)

    速度比100% 准确更重要的情况
    不能等待锁的释放

2.可提交读 


设置方式:SET ISOLATION TO COMMITTED READ;

  • 确保读取的所有记录都是提交到数据库
  • 能避免读到脏数据
  • 读到的所有的记录都是已提交的
  • 当一个进程读完记录后,其他进程就可以修改
  • 在读取数据前,数据库server尝试在记录上加共享锁

    加锁前,需要先检查是否可以对对象加共享锁,但是不加

    如果可以加锁,则要保证要加锁的记录没有其他进程正在更新

  • 当记录正在更新时,记录上有排他锁,此时我们不能对这些记录加共享锁


3.游标读

设置方式:SET ISOLATION TO CURSOR STABILITY;

  • 非更新CURSOR, 游标读的所有记录加上共享锁
  • 共享锁一致将保持,直到下一行记录被读取
  • 通过游标检索数据, 共享锁将一直保持到执行下一个 FETCH语句
  • 不仅可以看到提交的记录,也可以保证看到的记录不会被更新
  • 其他进程不能更新 (UPDATE or DELETE) 你所看到的记录
  • 当移动到下一行时,锁才会释放,记录就可以进行修改

4.可重复读

设置方式:SET ISOLATION TO REPEATABLE READ;

  • 数据库在读取的记录上加共享锁,验证是否可以读取数据
  • 直到事务提交,锁才能释放
  • 其他用户可以读取数据,但是不能修改
  • 可以保证在同一事务中前后两次读取记录是一致的
  • 当你必须要信任所有读取的记录,保证记录不被修改。我们可以采用repeatable read. 

    举例:

    关键的, 统计数据 (如:银行账号的余额情况)

    关联查询多个表

5.最后可提交读

设置方式: SET ISOLATION TO COMMITTED READ LAST COMMITTED

  • 解决Committed Read的不足: 记录被锁,其他进程需要等待;更新的记录不能访问,直到提交,除非采用脏读;由于需要等待更新记录的提交,应用程序性能较低;如果采用脏读则会得到非预期的结果;死锁的发生,也会消耗很多时间
    解决办法: Last Committed Read 
  • Committed Read 隔离级别, 由于其他session在记录上加了排他锁(行级锁),将导致读取数据失败SET ISOLATION COMMITTED READ 的LAST COMMITTED 可以降低读取数据的锁冲突


6.监控session的隔离级别指令

使用:onstat –g sql  或者  onstat –g ses
查看sid的详细信息:onstat –g sql sid


7.关于隔离级别的示例

(1)脏读

优点:并发性高,不需要锁资源  

缺点:脏读、幻影读、不可重复读

Session1

Session2

Session2 output

Begin work;
--With committed read default    Begin work;

Begin work;
Set isolation dirty read;

 

 

Select * from lock_tb where c1<=3;

1 abc
2 abc

Update lock_tb set c2='new' where c1=1;

Select * from lock_tb where c1<=3;

1 new
2 abc

Insert into lock_tb values(3, 'new');

Insert into lock_tb values(3, 'new');    Select * from lock_tb where c1<=3;
 

1 new
2 abc
3 new

Rollback; 

 

 

 

Select * from lock_tb where c1<=3;

1 abc
2 abc

--或者
Commit work;

 

 

 

Select * from lock_tb where c1<=3;

1 new
2 abc
3 new

(2)可提交读

优点:相对dirty read能避免脏读的问题
缺点:并发性较dirty read有所降低,容易出现锁等待引起的问题。不能解决幻影读、不可重复读

Session1

Session2

Session2 output

Begin work;
--With committed read default
set lock mode to wait 5;
Begin work;
set isolation committed read;
set lock mode to wait 5;
 
 Select * from lock_tb where c1<=3;1 abc
2 abc
Update lock_tb set c2='new' where c1=1;  
 Select * from lock_tb where c1<=3;SQL Error -244 锁错误


以上现象解释如下:

  • 因为 session2采用committed read对读取的记录不加S-LOCK,所以session1可以对该记录进行更新,并在该记录上加X-LOCK
  • session2采用committed read对读取的记录试图加S-LOCK,但检测到c1=1的记录上有X-LOCK,出现锁等待事件,超过锁等待时长5秒后报告锁等待超时错误:Error -244

Session1

Session2

Session2 output

Begin work;
--With committed read default
Set lock mode to wait 5;
Begin work;
Set isolation committed read;
Set lock mode to wait 5;
 
 Select * from lock_tb;1 abc
2 abc
update lock_tb set c2='new' where c1=1;
insert into lock_tb values(3, 'new');
  
Commit work;  
 Select * from lock_tb;
当session 1结束后执行
1 new
2 abc
3 new
--或者
Roll back; 
  
 Select * from lock_tb;
当session 1结束后执行
1 abc
2 abc

(3)可重复读

优点:能够解决脏读、幻影读和不可重复读的问题
缺点:只能串行执行,并发性低,需要对读取的记录加s-lock,容易引起锁相关的问题

   

Session1

Session2

Session2 output

Begin work;
--With committed read default
set lock mode to wait 5;    Begin work;
set isolation repeatable read;
Set lock mode to wait 5;
Begin work;
set isolation repeatable read;
Set lock mode to wait 5;    
 
Update lock_tb set c2='new' where c1=1;  
 Select * from lock_tb where c1<=3;SQL Error -244 锁错误
Insert into lock_tb values(3, 'new');  
Commit work;   


以上原因如下:

  • Session1对修改的的记录(c1=1)加X-LOCK
  • session2采用repeatable read需要对读取的记录(c1<=3)加S-LOCK,但是记录c1=1已经被加上了x-lock,故出现锁等待事件,当锁等待超时,则报告锁错误:Error -244

Session1

Session2

Session2 output

Begin work;
--With committed read default
Set lock mode to wait 5;
Begin work;
Set isolation repeatable read;
Set lock mode to wait 5;
 
Update lock_tb set c2='new‘ where c1=1;  
Insert into lock_tb values(3, 'new');  
Commit work;   
 Select * from lock_tb ;1 new
2 abc
3 new
--或者:
Rollback;
Select * from lock_tb ;1 abc
2 abc

 

(4)最后可提交读

优点:能解决脏读问题,并发性高;不需要锁资源,能避免committed read带来的锁问题,
缺点:幻影读、不可重复读

Session1

Session2

Session2 output

Begin work;
--With committed read default
set lock mode to wait 5;
Begin work;
set isolation to committed read last committed;
Set lock mode to wait 5;    
 
 Select * from lock_tb where c1>=3;1 abc
2 abc
update lock_tb set c2='new' where c1=1;  
     select * from lock_tb where c1>=3;1 abc
2 abc
Update lock_tb set c2='new' where c1=1;  
     Select * from lock_tb where c1>=3;1 abc
2 abc
rollback;   
 Select * from lock_tb where c1>=3;1 abc
2 abc
--或者
Commit work;
  
 Select * from lock_tb where c1>=3;1 new
2 abc
3 new

 

以上。如果你在GBase 8s的实际应用中遇到了棘手的锁冲突或隔离级别相关的问题,欢迎在南大通用技术社区分享讨论,我们一起寻找最优解!

评论

登录后才可以发表评论
gbase0001发表于 2个月前
感谢分享