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;

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

相关推荐
专注echarts研发20年8 小时前
Qt自定义双击事件实现方案(规避原生双击附带单击问题)
数据库
scugxl8 小时前
mysql federatedengine 使用
mysql
Linux蓝魔8 小时前
外网同步所有ubuntu源到内网使用
linux·数据库·ubuntu
墨香幽梦客8 小时前
系统性能优化技巧:数据库索引、缓存与异步处理的综合应用
数据库·缓存·性能优化
麦麦在写代码8 小时前
Mysql--DDL语句
数据库·mysql
x***r1518 小时前
oracle11.2.0.4安装步骤详解(附配置与连接教程)
oracle
2301_781392529 小时前
MySQL格式化数据展示——分页查询
java·数据库·mysql·性能优化
va学弟9 小时前
SQL 进阶知识——多表关联与约束
数据库·sql
一 乐9 小时前
学生宿舍管理|基于springboot + vue学生宿舍管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·助农电商系统