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;

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

相关推荐
小Mie不吃饭10 分钟前
Oracle - 闪回技术及生产实践
数据库·oracle
爱丽_14 分钟前
MyBatis事务管理与缓存机制详解
数据库·缓存·mybatis
Filotimo_17 分钟前
EntityGraph的概念
java·开发语言·数据库·oracle
tianyuanwo33 分钟前
RPM debugsource包的底层原理:深入解析rpmbuild 4.14中的调试源码打包机制
数据库·rpmbuild·debugsource
就叫飞六吧1 小时前
mysql表字段反查表名脚本-筛选法-查表技巧
数据库·mysql
1.14(java)1 小时前
MySQL数据库操作全攻略
java·数据库·mysql
jmxwzy1 小时前
MySQL
数据库·mysql
自己的九又四分之三站台2 小时前
PostgreSQL:万物皆可PostgreSQL的力量
数据库·postgresql
一条大祥脚2 小时前
25.12.30
数据库·redis·缓存
雨中飘荡的记忆2 小时前
MyBatis SQL执行模块详解
数据库·sql·mybatis