MySQL中的事务

事务

为了达成一个目的,需要进行一系列的操作,而这一系列的操作合在一起就是事务。

事务的特性

事务都具有ACID,即原子性(Automicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)。
原子性:事务中的一系列操作要么都成功,要么都失败。
一致性:事务执行时从一个状态转换成另一个状态,但是整个数据的完整性保持稳定。
隔离性:事务与事务之间互相隔离。
持久性:事务完成后对数据的改变是永久的。

通过一个例子来理解事务的特性

比如一次购买行为,购买时需要扣除购买人的余额,然后给商家增加收入,最后商品发货。这一整个过程就可以称为一个事务,如果购买的过程中出现异常比如在扣除购买人余额后出现了异常导致后面的流程无法进行,则会出现购买人余额扣除但商家未收到转账,所以一个事务要保证原子性。双方余额的总数在更改前后不变,保证了其一致性。事务结束后数据在库中保存保证了持久性。

事务的隔离级别

这里的事务隔离级别是基于MySQL的InnoDB引擎。
事务的隔离级别分别有,读未提交,读提交,可重复读,串行
其中读未提交其实就是不加事务,仅仅执行一条更新插入就是读未提交。
直接讲述概念并不能很好的理解这几种级别,下面过几个例子来进行说明。
有这么一张表:

CREATE TABLE `t` (
  `id` int NOT NULL,
  `a` int DEFAULT NULL,
  `t_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `t_modified` (`t_modified`)
) ENGINE=InnoDB;

INSERT INTO t VALUES(1,1,'2018-11-12 00:00:00');
INSERT INTO t VALUES(2,2,'2018-11-14 00:00:00');
INSERT INTO t VALUES(3,3,'2018-11-18 00:00:00');

同时有以下两个会话:

session Asession B
set session transaction isolation level READ COMMITTED;
begin;
select * from t where id=2;(2,2,'2018-11-14 00:00:00')
update t set a=4 where id=2;
select * from t where id=2;(2,4,'2018-11-14 00:00:00')
commit;

sessionA开启了一个事务,使用的级别是读提交,set session transaction isolation level READ COMMITTED可以将当前会话的隔离级别设置为读提交,第一次查询时记录还没有变化,此时sessionB修改了id=2的这行数据,事务中再次查询得到了最新结果,在一个事务中能读取到其他事务提交的结果这就是读提交。此时会带来不可重复读与幻读的问题。在上面的例子出现的就是不可重复读,一个事务内的数据前后读取值不一致。至于幻读暂时按下不表,让我们再看一个例子。

sessionAsessionB
set session transaction isolation level REPEATABLE READ;
begin;
select * from t where id=2;(2,4,'2018-11-14 00:00:00')
update t set a=2 where id=2;
select * from t where id=2;(2,4,'2018-11-14 00:00:00')
commit;
select * from t where id=2;(2,2,'2018-11-14 00:00:00')

MySQL的默认隔离级别就是可重复读,但是依然可以使用语句显示指定隔离级别,可以看到在可重复读的级别下在事务内读取到的数据始终是不变的,这样就避免了不可重复读的情况。当需要进行一些统计时会需要用到可重复读的隔离级别,比如在一个交易系统中我想统计到当前为止的支出,并不想让最近产生的更新影响到我,此时就需要可重复读。
幻读可以理解为在一个事务执行期间读取到另外一个事务插入的行。同样的可以通过例子来说明:

sessionAsessionB
begin;单元 2
select * from t where a=3 for update;(3,3,'2018-11-18 00:00:00')
insert into t values(4,3,'2018-12-01 00:00:00')
update t set a=a+1 where a=3;
commit;
select * from t where a=4;(3,4,'2018-11-18 00:00:00')(4,3,'2018-12-01 00:00:00')

出现上述情况则是出现了幻读,可以看到sessionA修改了sessionB新插入的数据这是不应该的。
对于串行,顾名思义就是一个接一个执行,因此效率最低。
隔离级别越高,效率就越低因此效率上来说:
读未提交>读提交>可重复读>串行

总结

本文主要讲述了以下几点:
1.事务的概念,事务的ACID特性。
2.事务的隔离级别,读未提交,读提交,可重复读,串行。
3.事务的不同隔离级别下会出现的问题,脏读,不可重复读,幻读。

6 声望
1 粉丝
0 条评论
推荐阅读
花了几个月时间把 MySQL 重新巩固了一遍,梳理了一篇几万字 “超硬核” 的保姆式学习教程!(持续更新中~)
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。

民工哥14阅读 1.9k

封面图
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.7k评论 2

封面图
Redis的线程模型和事务
我原本只是想学习Redis的事务,但后来发现,Redis和传统关系型数据库的事务在ACID的表现上差异很大。而要想详细了解其中的缘由,就离不开Redis独特的单线程模型,因此本文将二者联系在一起讲解。

KerryWu6阅读 6.1k评论 2

Spring系列-实战篇(5)-数据库的事务和锁
大学里面数据库课考试,事务和锁的相关知识绝对是要划的重点。数据库的事务要遵循ACID(原子性、一致性、隔离性、持久性)四要素,锁又有悲观锁和乐观锁的划分方式。那么今天我们讲讲,如何基于SpringBoot+Mybati...

KerryWu2阅读 6k评论 1

Vue+Express+Mysql全栈项目之增删改查、分页排序导出表格功能
本文记录一下实现一个全栈项目,前端使用vue框架、后端使用express框架、数据库使用mysql。此项目的意义不仅仅有助于我们复习nodejs相关知识、更有助于带前端新人,使其快速从整体全局角度中,理解常规后台管理系...

水冗水孚4阅读 2.6k

MySQL百万数据深度分页优化思路分析
一般在项目开发中会有很多的统计数据需要进行上报分析,一般在分析过后会在后台展示出来给运营和产品进行分页查看,最常见的一种就是根据日期进行筛选。这种统计数据随着时间的推移数据量会慢慢的变大,达到百万...

一个程序员的成长7阅读 868

封面图
深入理解MySQL索引底层数据结构
在日常工作中,我们会遇见一些慢SQL,在分析这些慢SQL时,我们通常会看下SQL的执行计划,验证SQL执行过程中有没有走索引。通常我们会调整一些查询条件,增加必要的索引,SQL执行效率就会提升几个数量级。我们有没...

京东云开发者3阅读 571

封面图
6 声望
1 粉丝
宣传栏