MYSQL---事务

本文将弄明白以下几个问题。

一、思考

问题一:事务是什么?为了解决什么问题?有哪些特性?

问题二:各种事务的隔离级别的区别?

二、分析

这篇文章先真正搞清楚事务的特性,并不分析事务的实现原理,如果想了解事务的实现原理,请移步【MYSQL---事务实现原理】。

2.1事务是什么

概念

来自于维基百科:

数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。

 目的

来自于维基百科:

事务包含了一个序列的对数据库的读写操作。其主要目的在于:

  1. 为数据库操作序列提供了一个从失败恢复到正常状态的方法,同时提供了数据库即使在异常状态下也能保持一致性的方法。
  2. 在多个应用程序并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作相互干扰。

 2.2事务特性

事务要实现上文所介绍的目的,必然要具备一定的特性(ACID):

原子性(Atomicity)

数据库事务作为一个整体,其包含的所有操作,要么全部被执行,要么全部不执行。

一致性(Consistency)

事务应确保数据库从一个一致性状态转变为另一个一致性状态。

隔离性(Isolation)

多个事务执行时,一个事务的执行不影响其他事务的执行。

持久性(Durability)

已提交的事务对数据库所做的更改,将永远保留在数据库中。

数据库的原子性可以通过回滚来控制(undolog)。一致性需要我们的业务逻辑支持,保证数据一致性,在数据库层面,只要事务执行过程中不发生异常,就认为一致。持久性通过确保对数据库的更改一定会被持久化到数据库文件(redolog)。这三点对于开发人员来说干涉较少,而对于隔离性,数据库提供了四种隔离级别,供我们选择,各有优缺点,请看下文。

2.3事务的隔离级别

事务共有四种隔离级别,在不同的隔离级别下可能会存在各种问题,比如脏读,不可重复读,幻读等。

相关名词

脏读

假设有事务A,B和数据D。

事务A读取了事务B修改的数据D,此时事务B还未提交,然后事务B又对修改进行了回滚或者再次修改,导致事务A读取到的数据是脏数据,称为脏读。

不可重复读

同一个事务内两次读取同一行数据的结果不一致。

幻读

同一事务内两个相同的查询语句得到的数据集不一致。

隔离级别设置

InnoDB提供了以下四种隔离级别:读未提交( READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)、可串行化(SERIALIZABLE)。

而默认的隔离级别为可重复读(RR)。我们可以通过以下参数重新设置事务的隔离级别:

隔离级别比较

假设有表t,字段(id,name);事务A和B。我们模拟不同隔离级别下的场景。

  • 读未提交( READ UNCOMMITTED)

未提交的事务数据也能被其他事务读到,举例

初始数据(1,‘zhangsan’),事务A和B执行顺序如下:

事务A事务B

SET autocommit=0;
START TRANSACTION;

SET autocommit=0;
START TRANSACTION;

//步骤一

UPDATE t SET name='a' WHERE id=1;    //name='a'

//步骤二(脏读)

SELECT name FROM t WHERE id=1;  //name='a';

 

 

//步骤三

....一些其他操作

 

 

//步骤四

UPDATE t SET name='b' WHERE id=1;     // name='b'

COMMIT;

//步骤五(不可重复读)

SELECT name FROM t WHERE id=1;  //name='b';

//步骤六

...一些其他操作

COMMIT;

 

问题

由上图可知,由于隔离级别为“读未提交”,事务A在步骤二中可读取到事务B未提交的数据,此时事务A认为name为a,便拿到这个值进行步骤三的其它业务逻辑操作,但是事务B在步骤四中又修改了name的值为b,导致事务A在步骤二中得到的数据变为脏数据,产生“脏读”现象,步骤三种的业务逻辑就可能出错。接下来步骤五中又读取name的值为b,发现和第一次读取的值不一样,导致步骤六可能出错,又产生了“不可重复读”现象。

综上所述,读未提交隔离级别,会产生“脏读”和“不可重复读”现象。

  • 读已提交(READ COMMITTED)

已经提交的事务数据才能被其他事务读到,举例

初始数据(1,‘zhangsan’),事务A和B执行顺序如下:

事务A事务B

SET autocommit=0;
START TRANSACTION;

SET autocommit=0;
START TRANSACTION;

//步骤一

UPDATE t SET name='a' WHERE id=1;    //name='a'

//步骤二(无脏读)

SELECT name FROM t WHERE id=1;  //name='zhangsan';

 

 

//步骤三

....一些其他操作

 

//步骤四

...一些其他操作

COMMIT;

//步骤五(不可重复读)

SELECT name FROM t WHERE id=1;  //name='a';

//步骤六

...一些其他操作

COMMIT;

 

问题

由上图可知,由于隔离级别为“读已提交”,故而事务A在步骤二中无法读取到事务B未提交的数据,所以事务A认为name为zhangsan,这个时候已经解决了“读未提交”中的“脏读”。但是当事务B提交事务之后,事务A中又在步骤五查询了name值,此时事务A读取到name为a,在事务A内两次读取到的name值不一致,导致接下来步骤六中的操作可能会出错,这便产生了“不可重复读”现象。

综上所述,在“读已提交”隔离级别下,虽然解决了“读未提交”中的脏读,但是“不可重复读”现象依然存在。

  • 可重复读(REPEATABLE READ)

只读取当前事务数据,举例

初始数据(1,‘zhangsan’),事务A和B执行顺序如下:

事务A事务B

SET autocommit=0;
START TRANSACTION;

SET autocommit=0;
START TRANSACTION;

//步骤一

UPDATE t SET name='a' WHERE id=1;    //name='a'

//步骤二(无脏读)

SELECT name FROM t WHERE id=1;  //name='zhangsan';

 

//步骤三

SELECT COUNT(*) FROM t WHERE id>=1;  //count=1;

 

 

//步骤四

....一些其他操作

 

 

 

//步骤五

UPDATE t SET name='b' WHERE id=1;     // name='b'

INSERT INTO t (id,name) VALUES (2,'lisi');

COMMIT;

//步骤六(无不可重复读)

SELECT name FROM t WHERE id=1;  //name='zhangsan';

//步骤七(幻读)

SELECT COUNT(*) FROM t WHERE id>=1;  //count=2;

COMMIT;

 

 

 

问题

由上图可知,由于隔离级别为“可重复读”,事务A无法读取到事务B“修改”的数据,所以不存在“脏读”和“不可重复读的情况”,但是对于事务“B”的插入操作,事务A却能读到(这个为什么能读到,等到我们后面博文分析事务的实现原理时再分析),此时对于事务A来说,两次读取的count值不一样,如同产生了幻觉一样,所以称为“幻读”现象。

综上所述,“可重复读”隔离级别解决了“脏读”、“不可重复”问题,但是存在“幻读”现象。

上面理论是这样,但是在博文【MYSQL---锁】中有提到,由于InnoDB采用了“间隙锁”,从而避免了在“可重复读”隔离级别下的幻读现象。即在“可重复读”隔离级别下是不存在幻读情况的。

  • 可串行化(SERIALIZABLE)

所有事务都按照顺序执行,不存在并发情况,所以当然就不存在“脏读”、“不可重复读”、“幻读”问题。

隔离级别选择

读完上述内容,或许你已经掌握了各种隔离级别的差异,那么你是否想过,为什么要设置这么多隔离级别,真实项目中如何选择使用哪个隔离级别,InnoDB引擎为什么要把“可重复读”作为默认隔离级别?

带着这个疑问,搜索了如下资料,觉得讲的很好,大家有兴趣可以仔细阅读:https://www.cnblogs.com/rjzheng/p/10510174.html

我从中做了如下总结(如果有疑问的还是请看上文链接地址):

  • 为什么InnoDB默认采用“可重复读”隔离级别?

由于历史存在的主从复制的一个bug,而当时的MYSQL版本通过“读已提交”隔离级别无法解决,所以采用“可重复读”隔离级别。而且毕竟“可重复读”解决了“不可重复读”和“幻读问题”。

  • 那真实项目中选用哪种隔离级别比较合适?

答案是“可重复读”隔离级别(建议,具体还得视情况而定)。原因如下:

首先,对于“读未提交”和“可串行化”我们一般不予考虑,因为前者会造成业务逻辑混乱,后者性能太差。这里主要讨论“读已提交”和“可重复读”,那为什么推荐“读已提交”,因为:

  1. “可重复读”存在“间隙锁”,提高了死锁发生的可能性。且由于“间隙锁”的存在,使得并发插入操作性能下降。
  2. 在“可重复读”隔离级别下,查询条件未命中,会加间隙锁;而“读已提交”隔离级别,不加锁。
  3. 在“读已提交”隔离级别下,半一致性读增加了update操作并发性。

那“读已提交”情况下的“不可重复读”和“幻读”问题,怎么办?

答案是既然已经提交的数据看到无所谓,但是需要我们业务逻辑的实现自行处理这种情况,否则可能出现逻辑错误。出于性能考虑还是“读已提交”更好。

三、其他 

如何查询正在执行的事务?

通过语句:SELECT * FROM information_schema.INNODB_TRX;

可重复读和读已提交差异的底层原理

请看博文:https://mp.csdn.net/postedit/102211569

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

至此,事务的基本内容已讲完,如果不对之处,还请指出探讨。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------参考博文:

  1. 互联网项目中MYSQL应该选用什么隔离级别:https://www.cnblogs.com/rjzheng/p/10510174.html
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于PyTorch的Embedding和LSTM的自动写诗实验LSTM (Long Short-Term Memory) 是一种特殊的循环神经网络(RNN)架构,用于处理具有长期依赖关系的序列数据。传统的RNN在处理长序列时往往会遇到梯度消失或梯度爆炸的问题,导致无法有效地捕捉长期依赖。LSTM通过引入门控机制(Gating Mechanism)和记忆单元(Memory Cell)来克服这些问题。 以下是LSTM的基本结构和主要组件: 记忆单元(Memory Cell):记忆单元是LSTM的核心,用于存储长期信息。它像一个传送带一样,在整个链上运行,只有一些小的线性交互。信息很容易地在其上保持不变。 输入门(Input Gate):输入门决定了哪些新的信息会被加入到记忆单元中。它由当前时刻的输入和上一时刻的隐藏状态共同决定。 遗忘门(Forget Gate):遗忘门决定了哪些信息会从记忆单元中被丢弃或遗忘。它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 输出门(Output Gate):输出门决定了哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。同样地,它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 LSTM的计算过程可以大致描述为: 通过遗忘门决定从记忆单元中丢弃哪些信息。 通过输入门决定哪些新的信息会被加入到记忆单元中。 更新记忆单元的状态。 通过输出门决定哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。 由于LSTM能够有效地处理长期依赖关系,它在许多序列建模任务中都取得了很好的效果,如语音识别、文本生成、机器翻译、时序预测等。
CSDN IT狂飙上传的代码均可运行,功能ok的情况下才上传的,直接替换数据即可使用,小白也能轻松上手 【资源说明】 基于MATLAB实现的这个代码主要是研究手写数字的识别效率,用卷积神经网络算法来实现,用的是官方手写字体数据,能够显现百分之九十以上的识别率+使用说明文档 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2020b;若运行有误,根据提示GPT修改;若不会,私信博主(问题描述要详细); 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可后台私信博主; 4.1 期刊或参考文献复现 4.2 Matlab程序定制 4.3 科研合作 功率谱估计: 故障诊断分析: 雷达通信:雷达LFM、MIMO、成像、定位、干扰、检测、信号分析、脉冲压缩 滤波估计:SOC估计 目标定位:WSN定位、滤波跟踪、目标定位 生物电信号:肌电信号EMG、脑电信号EEG、心电信号ECG 通信系统:DOA估计、编码译码、变分模态分解、管道泄漏、滤波器、数字信号处理+传输+分析+去噪、数字信号调制、误码率、信号估计、DTMF、信号检测识别融合、LEACH协议、信号检测、水声通信 5、欢迎下载,沟通交流,互相学习,共同进步!
基于LSTM+CNN的自然语言处理,基于单维LSTM、多维LSTM时序预测算法和多元线性回归算法的预测模型LSTM (Long Short-Term Memory) 是一种特殊的循环神经网络(RNN)架构,用于处理具有长期依赖关系的序列数据。传统的RNN在处理长序列时往往会遇到梯度消失或梯度爆炸的问题,导致无法有效地捕捉长期依赖。LSTM通过引入门控机制(Gating Mechanism)和记忆单元(Memory Cell)来克服这些问题。 以下是LSTM的基本结构和主要组件: 记忆单元(Memory Cell):记忆单元是LSTM的核心,用于存储长期信息。它像一个传送带一样,在整个链上运行,只有一些小的线性交互。信息很容易地在其上保持不变。 输入门(Input Gate):输入门决定了哪些新的信息会被加入到记忆单元中。它由当前时刻的输入和上一时刻的隐藏状态共同决定。 遗忘门(Forget Gate):遗忘门决定了哪些信息会从记忆单元中被丢弃或遗忘。它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 输出门(Output Gate):输出门决定了哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。同样地,它也由当前时刻的输入和上一时刻的隐藏状态共同决定。 LSTM的计算过程可以大致描述为: 通过遗忘门决定从记忆单元中丢弃哪些信息。 通过输入门决定哪些新的信息会被加入到记忆单元中。 更新记忆单元的状态。 通过输出门决定哪些信息会从记忆单元中输出到当前时刻的隐藏状态中。 由于LSTM能够有效地处理长期依赖关系,它在许多序列建模任务中都取得了很好的效果,如语音识别、文本生成、机器翻译、时序预测等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值