南大通用GBase 8s 数据库封锁与并发事务调度介绍

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 南大通用GBase 8s 数据库封锁与并发事务调度介绍

本文探讨GBase 8s的事务处理特性,揭示它是如何确保ACID特性,并有效管理并发事务的。

事务的概念
将用户在数据库中的某些操作集合看作一个整体,在其有序执行的过程中不被其他操作影响,这样的操作集合就是事务。
事务(Transaction)是对数据库进行操作的集合。该集合是一个不可分割的具有逻辑功能的工作单元,集合中的操作在事务的一次执行中必须全部被执行或者全部。
事务的特性(ACID 特性)
Atomicity: 原子性,构成该事务的操作集合中的全部操作在事务的运行过程中全部执行或者全部不执行。
Consistency: 一致性,事务运行的结果应该使数据库保持数据一致性。
Isolation:隔离性,构成某个事务的全部操作与其他事务或操作是隔离的,同时执行的事务之间不能够互相影响,一个事务单独运行的结果应该与该事务和其他多个事务同时运行的结果一致。
Durability: 持久性,事务的持久性是指事务运行完毕并成功提交后,其对数据库全部操作的结果应该永久地保留在数据库中。
并发事务的调度
1、并发问题和并发操作
实际应用中,通常会有来自不同用户的多个事务并发执行,事务之间会有交叉,这个问题就是事务的并发问题。
并发事务之间相互影响,会破坏相关事务的正常运行,无法保证事务的 ACID 特性,产生数据错误。
并发操作(Simultaneous Concurrency)对于数据库的并发操作是由并发运行的多个事务引起的,是并发事务中包含的对数据库的操作。
并发操作是由多个事务并发进行而产生的,其最大问题是容易导致数据库的不一致性
举例说明

两个售票点同时售出同一天同一车次的车票,第一个售票点执行的数据库事务 T1 为:

(1)读出当前车票的剩余数量 A,假设 A=50;

(2)售出一张票,剩余数量变为 A=A-1,即 A=49。

第二个售票点执行的数据库事务 T2 为:

(1)读出当前车票的剩余数量 A,假设 A=50;

(2)售出一张票,剩余数量变为 A=A-1,即 A=49。

事务 T1 和 T2 按照如下顺序并发执行:

(1)读出当前车票的剩余数量 A,假设 A=50;

(2)读出当前车票的剩余数量 A,假设 A=50;

(3)售出一张票,剩余数量变为 A=A-1,即 A=49;

(4)售出一张票,剩余数量变为 A=A-1,即 A=49。

事务执行的结果是只卖了一张车票,而实际上售出了两张,这样就可能导致同一个座位售出两张车票,数据库出现了数据的不一致性错误。

并发操作导致数据库出现数据不一致性的问题,如下表所示。事务 T1 将数据对象,即火车票的总数 A 进行了修改,变为 49,而事务 T2 在 T1 修改 A 之前读取的 A 的值仍然

是 50,T2 将此值修改为 49 后写回数据库并覆盖了 T1 事务对 A 的修改,此时,A 的值为49,就会出现这种情况:卖出两张车票后车票总数应为 48,而数据库中车票的总数为 49,

显然出现了数据的不一致性错误。

2、调度
调度(Schedule)是指事务的执行次序。
如果多个事务依次执行,则称为事务的串行调度(Serial Schedule)。
如果多个事务同时执行,则称为事务的并发调度(Concurrent Schedule)
3、冲突
冲突(conflict):事务调度中的两个操作(读操作或写操作),如果交换顺序执行,它们所属的事务运行结果会改变,那么这两个操作就被称为冲突。
不同事务对于不同数据对象进行操作(无论是读操作还是写操作)不会产生冲突;不同事务对同一数据对象进行读操作也不会产生冲突。
4、封锁
并发控制的主要技术是封锁(Locking)
封锁的对象是数据库中的数据对象,如关系型数据库中的表、记录、属性、索引等
对数据对象加锁的时机是在事务对其进行操作之前,向系统发出加锁请求。
加锁后事务 T就取得了对该数据对象的控制,在事务 T 释放它的锁之前,其他事务不能对此数据对象进行任何操作。
封锁是一种排队机制,将并行任务按锁的先后顺序排队,把并行任务变成串行任务。
5、封锁产生的问题
封锁技术在一定程度上解决了数据库的并发事务处理过程中,并发操作给数据库带来的数据一致性问题,但同时产生了新的问题如活锁和死锁。

活锁问题
在处理并发事务的过程中,如果事务 T1 在数据对象 R 上加锁,事务 T2 又请求为数据 对象 R 加锁,则 T2 必须等待 T1 释放加在 R 上的锁。如果事务 T3 也请求为 R 加锁,当 T1 释放了 R 上的锁之后系统首先响应 T3 的请求,则允许 T3 对 R 加锁,此时 T2 仍需等 待 T3 释放加在 R 上的锁。然后事务 T4 又请求封锁 R,当 T3 释放了 R 上的封锁之后系统 又响应了 T4 的请求……T2 有可能永远等待而无法为 R 加锁,这就是活锁。

活锁也称饿死,由于事务永远得不到封锁而导致。避免活锁可以采用先来先服务的策略。当多个事务请求封锁同一个数据对象时,可按照请求封锁的先后次序对事务排队,数据对象上的锁一旦释放就批准申请队列的第一个事务获得封锁。 

T1

T2

T3

T4

LOCK (R)

……

……

UNLOCK (R)

LOCK (R)

等待

等待

等待

等待

LOCK (R)

等待

LOCK (R)

……

UNLOCK (R)

LOCK (R)

等待

等待

等待

LOCK (R)

……

死锁问题
如果事务 T1 对数据对象 R1 进行封锁,T2 对数据对象 R2 进行封锁,然后 T1 又请求对 R2 进行封锁,由于 T2 已封锁了 R2,则 T1 必须等待 T2 释放 R2 上的锁。接着 T2 又申请对 R1 进行封锁,由于 T1 已封锁 R1,因此,T2 也只能等待 T1 释放 R1 上的锁。这样就出现了事务 T1 等待另一个事务 T2 释放相关数据对象上的锁,而 T2 又在等待 T1 释放相关对象上的锁,T1 和 T2 两个事务由于相互等待对方释放数据对象上的锁而永远不能继续执行,这样就出现了死锁。

死锁(Dead Lock):系统中有两个或两个以上的事务都处于等待状态,并且每个事务都在等待其中另一个事务释放封锁,这样才能继续执行下去,结果造成任何一个事务都无法继续执行,这种现象称数据库系统进入了“死锁”(Dead Lock)状态

用例简单复现死锁产生

GBase模式下(会话1):

Create database if not exists testdb with buffered log;
Database testdb;
Create table if not exists a(c1 int,c2 int);
Create table if not exists b(c1 int,c2 int);
Insert into a values(1,1);
Insert into a values(2,2);
Insert into b values(1,1);
Insert into b values(1,1);
!sh /tmp/rd129/onmode_I143_rd129
Set isolation to repeatable read;
Set lock mode to wait;
Begin;
Select *from b;                   --读b表,对b表加上S锁
!echo “sql start sleep 5!sleep 15
!echo “sql sleep 5 done”
Update a set c1=6 where c2=2;     -更新a表,想对a表加上X锁
Commit;
Close database;
!cat /tmp/rd129/out.log
Drop database testdb;

onmode_I143_rd129内容如下(会话2):
Onmode -I 143
(
Dbaccess -e-m testdb - <<!
Set isolation to repeatable read;
Set lock mode to wait;
Begin;
Select * from a;                 --读a表,对a表加上S锁
!echo “sql start sleep 5!sleep 10
!echo “sql sleep 5 done”
Update b set c1=6 where c2=2;   --更新b表,想对b表加上X锁
Commit;
!
) >/tmp/rd129/out.log 2>&1 &

那么两个会话分别在同一个库中,对a表和b表加上共享锁S,当想进行更新时,会话1在等待会话2释放a的S锁,而会话2在等待会话1释放b的S锁,从而导致死锁产生。

那么在oracle模式下,该用例却不能产生死锁。

因为在GBase模式下,开启事务后,可以保证两个会话在执行更新后才提交保证两个会话同时进行。

而在oracle模式下,只能开启多语句模式,DML语句会自动开启事务,通过commit/rollback结束事务,DDL会提交事务。从而导致两个会话可能无法同时进行,因此并行变成串行,导致死锁无法产生。

南大通用GBase 8s数据库的事务处理能力和并发控制机制,为企业提供了一个可靠、高效和安全的数据处理平台。无论是金融交易还是在线事务处理,GBase 8s都能确保数据的完整性和一致性,满足企业对数据库系统的要求。

相关文章
|
2月前
|
Linux 数据库 数据安全/隐私保护
GBase 数据库 加密客户端---数据库用户口令非明文存放需求的实现
GBase 数据库 加密客户端---数据库用户口令非明文存放需求的实现
|
2月前
|
SQL 存储 BI
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
|
2月前
|
SQL 数据库
gbase 8a 数据库 SQL优化案例-关联顺序优化
gbase 8a 数据库 SQL优化案例-关联顺序优化
|
2月前
|
数据库连接 Linux Shell
Linux下ODBC与 南大通用GBase 8s数据库的无缝连接配置指南
本文详细介绍在Linux系统下配置GBase 8s数据库ODBC的过程,涵盖环境变量设置、ODBC配置文件编辑及连接测试等步骤。首先配置数据库环境变量如GBASEDBTDIR、PATH等,接着修改odbcinst.ini和odbc.ini文件,指定驱动路径、数据库名称等信息,最后通过catalog.c工具或isql命令验证ODBC连接是否成功。
|
2月前
|
JSON JavaScript 关系型数据库
node.js连接GBase 8a 数据库 并进行查询代码示例
node.js连接GBase 8a 数据库 并进行查询代码示例
|
2月前
|
SQL 数据库
gbase 8a 数据库 shm满导致gclusterd进程异常
gbase 8a 数据库 shm满导致gclusterd进程异常
|
2月前
|
网络安全 数据库
gbase 8a 数据库 安装8ampp 常见ssh报错问题
gbase 8a 数据库 安装8ampp 常见ssh报错问题
|
2月前
|
存储 机器学习/深度学习 监控
南大通用GBase 8s数据库onbar基础使用教程
数据备份与恢复是确保数据安全和业务连续性的关键。onbar作为GBase 8s数据库的备份工具,需配合存储管理器使用,通过配置BAR_BSALIB_PATH等参数,实现数据的备份与恢复。本文详细介绍了onbar的配置、备份、恢复及监控流程,帮助数据库管理员构建高效的数据保护方案。
|
2月前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
|
2月前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(下)
本文接续前文,深入讲解了在Windows环境下使用C#和ADO.NET操作南大通用GBase 8s数据库的方法。通过Visual Studio 2022创建项目,添加GBase 8s的DLL引用,并提供了详细的C#代码示例,涵盖数据库连接、表的创建与修改、数据的增删查改等操作,旨在帮助开发者提高数据库管理效率。