为了更好的理解@Transactional的内容,讨论一些数据库的特性
1.数据库事务ACID特性
数据库事务正确执行的四个基础要素是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
- 原子性:是指事务包含的所有操作要么全部成功,要么全部失败回滚,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有被执行过一样。
-
一致性:是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
-
隔离性:两个事务之间的隔离程度
-
持久性
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
2 丢失更新
在互联网中存在着抢购、秒杀等高并发环境,使得数据库在一个多事务的环境中运行,多个事务的并发会产生一系列的问题,主要的问题之一就是丢失更新,一般而言存在两类丢失更新。
假设一个场景,一个账户存在互联网消费和刷卡消费两种形式,而一对夫妻共用这个账户。老公喜欢刷卡消费,老婆喜欢互联网消费,那么可能产生如下表所示场景
表1 第一类丢失更新
时间 |
事务一(老公) |
事务二(老婆) |
T1 |
查询账户余额为10000元 |
|
T2 |
|
查询账户余额为10000元 |
T3 |
|
网购1000元 |
T4 |
请客吃饭消费1000元 |
|
T5 |
提交事务成功,余额9000元 |
|
T6 |
|
取消购买,回滚事务到T2时刻,余额10000元 |
整个过程只有老公消费1000元,而在最后的T6时刻,老婆回滚事务,却恢复了原来的初始值10000元,这显然不符合事实。这样的两个事务并发,一个回滚、一个提交成功导致不一致,称之为第一类丢失更新。大部分数据库(包括Mysql和Oracle)基本都已经消灭了这类丢失更新。
第二类丢失更新是我们真正需要关注的内容,还是上面的例子,如表2所示
表2 第二类丢失更新
时间 |
事务一(老公) |
事务二(老婆) |
T1 |
查询账户余额为10000元 |
|
T2 |
|
查询账户余额为10000元 |
T3 |
|
网购1000元 |
T4 |
请客吃饭消费1000元 |
|
T5 |
提交事务成功,余额9000元 |
|
T6 |
|
提交事务,根据之前余额10000元,扣减1000元后,余额为9000元 |
整个过程存在两笔交易,一笔是老公的请客吃饭,一笔是老婆的网购,两者都提交了事务,由于在不同的事务中,无法探知其它事务的操作,导致两者提交后,余额都为9000元,而实际正确的应为8000元,这就是第二类丢失更新。为了克服事务之间协助的一致性,数据库标准规范中定义了事务之间的隔离级别,来在不同程度上减少出现丢失更新的可能性---->数据库隔离级别。
隔离级别
隔离级别可以在不同程度上减少丢失更新,按照SQL的标准规范,把隔离级别定义为4层,分别是:脏读(dirty read)、读/写提交(read commit)、可重复读(repeatable read)和序列化(serializable)。
脏读是最低的隔离级别,允许一个事务去读取另一个事务中未提交的数据。
表3 脏读
时间 |
事务一(老公) |
事务二(老婆) |
备注 |
T1 |
查询余额10000元 |
|
|
T2 |
|
查询余额10000元 |
|
T3 |
|
网购1000元,余额9000元 |
|
T4 |
请客吃饭消费1000元,余额8000元 |
|
读取到事务二,未提交余额为9000元,所以余额为8000元 |
T5 |
提交事务 |
|
余额为8000元 |
T6 |
|
回滚事务 |
由于第一类丢失更新已经克服,所以余额为错误的8000元 |
由于在T3时刻老婆启动了消费,导致余额为9000元,老公在T4时刻消费,因为用了脏读,所以能够读取老婆消费的余额(事务二未提交的)为9000元,这样余额就为8000元了,于是T5时刻老公提价事务,余额变为了8000元,老婆在T6时刻回滚事务,由于第一类丢失更新已经克服,所以余额为错误的8000元,显然这是一个错误的余额,产生这个错误的根源来自于T4时刻,也就是事务一读取到事务二未提交的事务,这样的场景称之为脏读。
为了克服脏读,SQL标准提出了第二个隔离级别----读/写提交。所谓读写提交,就是说一个事务只能读取另一个事务已经提交的数据。
表4 读/写提交
时间 |
事务一(老公) |
事务二(老婆) |
备注 |
T1 |
查询余额10000元 |
|
|
T2 |
|
查询余额10000元 |
|
T3 |
|
网购1000元,余额9000元 |
|
T4 |
请客吃饭消费1000元,余额9000元 |
|
由于事务二的余额未提交,采取读/写提交时不能读出,所以余额为9000元 |
T5 |
提交事务 |
|
余额为9000元 |
T6 |
|
回滚事务 |
由于第一类丢失更新已经克服,所以余额依旧为正确的9000元 |
在T3时刻由于事务采取读/写提交的隔离级别,所以老公无法读取老婆未提交的9000元余额,他只能读取到10000元,所以在消费后余额依旧为9000元。T5时刻提交事务,而T6时刻老婆回滚事务,所以结果为正确的9000元,这样就消除了脏读带来的问题,但是也会引发其它问题,如下表所示。
表5 不可重复读
时间 |
事务一(老公) |
事务二(老婆) |
备注 |
T1 |
查询余额10000元 |
|
|
T2 |
|
查询余额10000元 |
|
T3 |
|
网购1000元,余额9000元 |
|
T4 |
请客吃饭消费2000元,余额8000元 |
|
由于采取读/写提交,不能读取事务二中未提交的余额9000元 |
T5 |
|
继续购物8000元,余额1000元 |
由于采取读/写提交,不能读取事务一中未提交的余额8000元 |
T6 |
|
提交事务,余额1000元 |
老婆提交事务,余额更新为1000元 |
T7 |
提交事务发现余额为1000元,不足以买单 |
由于采取读/写提交,因此此时事务一可以知道余额不足 |
由于T7时刻事务一知道事务二提交的结果----余额为1000元,导致老公无钱买单的尴尬。对于老公而言,他并不知道老婆做了什么事情,但是账户余额却莫名其妙地从10000元变为了1000元,对他来说,账户余额是不能重复读取的,而是一个会变化的值,这样的场景称之为不可重复读(unrepeatable read),这是读/写提交存在的问题。
为了克服不可重复读带来的错误,SQL标准又提出了一个可重复读的隔离级别来解决问题。注意,可重复读针对的是数据库同一条记录而言的,换句话说,可重复读会使得同一条记录的读/写按照一个序列化进行操作,不会产生交叉情况,这样就能保证同一条数据的一致性,进而保证上述场景的正确性。但是由于数据库并不是只能针对一条数据进行读/写操作,在很多场景,数据库需要同时对多条记录进行读/写,这个时候会产生下面的情况。如下表所示
表6 幻读
时间 |
事务一(老公) |
事务二(老婆) |
备注 |
T1 |
|
查询消费记录为10条,准备打印 |
初始状态 |
T2 |
启用消费一笔 |
|
|
T3 |
提价事务 |
|
|
T4 |
|
打印消费记录得到11条 |
老婆发现打印了11条消费记录,比查询的10条多了一条。她会认为这条是多余不存在的,这样的场景称之为幻读。 |
老婆在T1查询得到10条记录,到T4打印记录时,并不知道老公在T2和T3时刻进行了消费,导致多一条(可重复读针对的是同一条记录,而这里不是同一条记录)消费记录的产生,她会质疑这条多出来的记录是不是幻读出来的,这样的场景称之为幻读。
为了克服幻读,SQL标准又提出了序列化的隔离级别。它是一种让SQL按照顺序读/写的方式,能够消除数据库事务之间并发产生数据不一致的问题。
表7 各类隔离级别和产生的现象
隔离级别 |
脏读 |
不可重复读 |
幻读 |
脏读 |
√ |
√ |
√ |
读/写提交 |
× |
√
|
√ |
可重复读 |
× |
× |
√ |
序列化 |
× |
× |
× |
相关推荐
Day025 数据库相关知识
教程名称:MySQL数据库相关知识课程目录:【】mysql异地数据库备份实例代码【】MySQL数据库双机热备份如何实现【】MySQL数据库备份的简单知识【】MySQL数据库恢复过程【】SQL索引失效的5种情况分析【】windows下如何...
数据库基础知识概述 本篇资源摘要信息将对数据库基础知识进行概述,主要涵盖数据库的基本概念、组成、安装与系统结构、数据库及表的操作、日常使用与管理、语言、性能问题等方面。 数据库基础知识 数据库系统是指...
看看……可以给你帮助 互相学习数据库相关的知识数据库相关的知识
- **数据库(DB)**:存储相关数据的集合,具备共享性、低冗余度和紧密联系的特点,同时支持程序与数据的独立性。 - **数据库管理系统(DBMS)**:位于用户与操作系统间的软件,负责数据的存储、查询、更新和控制,...
数据库基础知识培训 本文档主要介绍了数据库基础...数据库基础知识培训是学习和掌握数据库相关知识的基础,本文档涵盖了数据库基础概念、常用的数据库管理系统、数据库体系结构等知识点,为用户提供了充分的学习资源。
数据库是信息时代的核心,它是组织、存储和管理数据的系统,对于任何想要深入理解数据处理的初学者来说,掌握数据库知识至关重要。本文将详细介绍数据库的基本概念、类型、以及关系数据库的标准语言SQL。 首先,...
Mysql数据库知识.xmind
从SQL的基础知识到数据库的高级应用,再到大数据环境下的数据处理,本系列课程将带领学习者逐步深入,掌握数据库技术的核心概念和实践技能。 适合人群:本系列课程适合希望提升数据库技能的中级程序员,尤其是那些...
本文将深入探讨数据库的基础知识,包括数据库的定义、类型、模型、SQL语言以及数据库管理系统(DBMS)等相关概念。 1. 数据库定义:数据库是一个有组织的、可共享的、持久存储的数据集合,用于高效地获取和管理信息...
文章最后给出了一个具体的例子,展示了如何利用基于关系数据库的知识库进行推理的过程,并实现了相关的编程。 #### 五、总结 综上所述,基于关系数据库的知识库设计是一种有效的知识管理方案。通过合理利用数据库...
数据的语义与其表示密切相关,同一数值在不同情境下有不同的含义。例如,数字500可以代表价格、人数或重量。随着计算机技术的发展,数据类型变得越来越复杂,数据的语义也更加丰富。 数据库,简称DB,是长期存储在...
数据库课程的详细介绍。...它详细介绍了数据库的相关知识, 介绍了数据库的相关知识 数据库课程的详细介绍。希望可以帮助一部分人下载。 它详细介绍了数据库的相关知识, 介绍了数据库的相关知识
如何对数据库进行有效的知识产权保护引起了全世界的广泛重视,各国 的处理方法各不相同,主要是通过版权、数据库特殊权利等进行保护,这几种方式各 有其优点和缺陷。而我国相关立法相对滞后,现行《著作权法》无论是在...
数据库是计算机科学中用于存储和管理数据的核心工具,SQL...理解并熟练运用这些SQL基础知识,对于参加数据库相关的笔试至关重要。通过不断的练习和实践,你将能更有效地管理和操作数据库,从而在笔试中脱颖而出。
随着技术的发展,数据库系统不断进化,为了满足不同的需求,开发者可以根据实际应用场景选择合适的数据库系统,并掌握相关的操作技能。在数据管理、数据安全和数据备份方面也需要不断学习和实践,以保证数据的完整性...
Access数据库第一章基础知识,包含数据库的相关概念、关系数据库、数据库设计的步骤、SQL基本命令、Access简介
数据库知识,讲解基本的增删改查,排序以及分组方法,讲解全面,易于理解,能开发者能够在短时间内了解数据库相关知识,