MYSQL 事务-1

并发访问

在mysql中事务是一个用于解决数据库并发访问的功能,主要运用与读写并发中。

当多个数据库客户端同时访问数据库时,有一些客户端可能对数据库进行增删改操作,有一些可能对数据库进行读取操作,那么如何能保证数据完整性和一致性呢,最方便的方法就是加锁,mysql也是一个进程,只需要对增删查改等各种操作加上锁就可以解决数据不一致的问题。

就如同进程并发时,以抢票系统为例,我们需要先判断是否还有票,这就需要查看数据库中对应的票数量是否为0,进入之后需要对这个数据进行update将其票数量值减1,但是多个进程时并发运行的,此进程通过了判断逻辑但是还没又对数据进行更新,这时另外一个抢票进程又来,上一个进程就被挂起了,新进来的进程也进入了并将票数量进行了更新,若是此时票已经为0了,那么当挂起的进程从新获得时间片之后,那么对数据进行的操作将是不合法的,因为票已经没有了。

在进程中我们一般会为这个抢票逻辑加上锁,一旦有进程进入此段代码,其他的进程都只能等待锁的释放,获得锁才能进入。这就保证了抢票这段代码的原子性。

此逻辑在mysql也是一样的,当有多个客户端同时对同一个数据库内的同一行记录进行修改时,mysql也是需要对其进行加锁,直到持有锁的将锁释放掉才能对其进行操作。

加锁与效率

读写是否需要加锁呢?如上例子,读写进行并发也是需要保证整个过程的数据的一致性和正确性的,不然读取时是有票的,但是还没进行下一步的操作,已经被其他客户端更改了数据,那么以原数据为基准进行的操作就肯定是错误的。

但是对数据库的访问可能不只一两个客户端,可能会有大量的客户端进行对数据库的访问,而且操作可能也有长操作,短操作。不能让一个客户端就完全占用了数据库而禁止其他客户端的访问。所以后来mysql加入的事务用与处理并发访问的问题,事务最开始并不存在于mysql中的,而是后续经过实际使用后,对应需求而加入的功能。

什么是事务

事务就是我们需要对数据进行的一个完整的操作的总合,如抢票,我们需要先查询票数量就是select语句,获取其数据后判断票是大于0的我们还需要对数据进行update将票--,那么这两条语句就是我们需要对这个数据的一个完整的操作,两个语句统合成一个事务。

为了处理并发访问导致的问题,事务拥有4个属性

  • 原子性: 为了解决并发导致的数据不一致问题,需要对应的操作要具有原子性。mysql中将一条或多条DML语句(CURD)组成一组,这一组语句就是一个事务,这一整个事务是原子性的,从开始,到结束,在外部看来是只有两个状态,一个是什么事都没做,一个已经完成了事务中的所有操作的两个状态。
  • 隔离性:数据库是允许多个事务并发进行的,那么对事务与事务之间进行隔离,以保证每个事务获取到的数据能满足一致性,防止事务的交叉执行的干扰,事务隔离分为不同的级别:读未提交(read uncommitted),读提交(read committed),可重复读(repeatable read),串行化(serializable)。
  • 持久性:当事务结束后,对数据修改就是永久的,即使故障也不会丢失。
  • 一致性:上面三条就是为了保证数据的一致性。事务开始与结束之后,数据库的完整性没有被破坏,事务对数据的修改是完全符合预设规则,包含资料的精确度,串联性,以及后续数据库可以自发地完成预定的工作。

在mysql中只有innodb数据库引擎是支持事务的。

复制代码
MariaDB [(none)]> show engines\G

如图只有InnoDB中的Comment字段中有Supports transactions。

Savepoints是指事务保存点。

自动提交

使用innodb引擎的数据库中,当我们输入一段DML语句时其实就已经经历了一次事务了如

复制代码
select * from table_name;

这条语句也是一个事务,在mysql中默认是自动对事务进行提交的

复制代码
MariaDB [(none)]> show variables like 'autocommit';

这时代表事务自动提交以开启。

这个当然时可以更改的。

复制代码
MariaDB [(none)]> set autocommit=0;

这是之影响当前正在运行的客户端。

现在有一张表

同时打开两个客户端,我们使用关闭了自动提交事务的客户端对此表进行插入

复制代码
 insert into student values(7,'alies',2ies',2);

进行了插入后我们再使用另外一个客户端对表进行查询结果如下

这里是没有id为7的一行记录的。这就是事务的原子性-两个状态,因为此事务还没有完成即还没有提交,所以,在其他事务中看起来就是什么都没做,直到我们输入

复制代码
MariaDB [test_db]> commit;

这时,就能从其他客户端中看到这条记录了。

相关推荐
雨中飘荡的记忆2 小时前
MySQL + Redis 分布式事务消息中间件:保证最终一致性
redis·mysql
chian_ocean2 小时前
在 KubeSphere 上部署 AI 大模型 Ollama
数据库
BullSmall2 小时前
MySQL8.0连接数查询全攻略
mysql
跟着珅聪学java2 小时前
Jedis SetParams教程:参数化设置 Redis 键值对
数据库·redis·缓存
一颗宁檬不酸2 小时前
数据库开发实战案例分享:从函数到存储过程的应用
数据库·数据库开发
北京中邦兴业2 小时前
GMP洁净环境监测法规深度解读:构建以风险为核心的动态防御体系
数据库·人工智能·面试·职场和发展
TDengine (老段)2 小时前
人力减 60%:时序数据库 TDengine 助力桂冠电力实现 AI 智能巡检
java·大数据·数据库·人工智能·时序数据库·tdengine·涛思数据
潇I洒2 小时前
Ubuntu Linux 24.04 安装MySQL 8.4.7
linux·数据库·mysql·ubuntu
milanyangbo2 小时前
像Git一样管理数据:深入解析数据库并发控制MVCC的实现
服务器·数据库·git·后端·mysql·架构·系统架构