70 mysql 中事务的隔离级别

前言

mysql 隔离级别有四种 未提交读, 已提交读, 可重复度, 序列化执行

然后不同的隔离级别存在不同的问题 

未提交读存在 脏读, 不可重复度, 幻觉读 等问题

已提交读存在 不可重复度, 幻觉读 等问题

可重复读存在 幻觉读 等问题

序列化执行 没有以上问题

然后 我们这里 来调试一下 以上各个事务隔离级别中存在的对应的问题

 

 

未提交读 READ_UNCOMMITTED

脏读

执行序列如下 

tx1 : begin;
tx2 : begin;
tx1 : select * from tz_test_02 where id = 5;
tx2 : update tz_test_02 set field1 = 'field1_updated', field2 = 'field2_updated' where id = 5;
tx1 : select * from tz_test_02 where id = 5;
tx1 : commit;
tx2 : commit;

 

然后 我们这里核心关注的是 第三条语句, 和 第五条语句的执行结果

第三条语句的执行, 根据主键定位到对应的记录的位置, 获取记录 判断是否匹配条件

3006d46e30e981b9b7bad3322a632099.png

 

这个 row_search_mvcc 依次会遍历两次, 第一次定位到的是 id=5 的记录 

第二次是 继续向下迭代, 找到的下一条记录 id=10, 接着跳出 

e2b112b328fc34e390a1a2cfc5807078.png

 

第四条语句的执行, 标记删除原有的记录, 新增新的记录如下 

e41be67fbce1f32bd9c50f26117e85e5.png

 

第五条语句的执行, 可以看到这里的 rec 即为上面 update 操作之后新增的 rec 

因此这个可以理解为一个 “无锁”状态的隔离级别

f3779a35ddc8da234a04111d5b2b76b5.png

 

 

可重复度

未提交读 存在脏读问题, 那么就一定存在 可重复度的问题

这里不再赘述, 调试这一过程 

事务1开始事务
事务1 查询 id 为 5 的记录, 发现记录为 field1 字段为 ”field1” 
事务2开始事务
事务2插入 id 为 5 的记录
事务2提交事务 
事务1 查询 id 为 5 的记录, 发现记录为 field1 字段为 ”field1_updated” 
事务1提交

 

 

幻觉读

未提交读 存在不可重复读问题, 那么就存在 幻觉读的问题

这里不再赘述, 调试这一过程 

事务1开始事务
事务1 查询 id 为 20 的记录, 发现不存在 
事务2开始事务
事务2插入 id 为 20 的记录
事务2提交事务 
事务1 查询 id 为 20 的记录, 发现存在 
事务1提交

 

 

已提交读 READ_COMMITTED

脏读

已提交读, 无脏读问题, 主要是基于 MVVC 来解决脏读的问题的

执行序列如下, 我们这里更加关心的是 id=5 的记录的更新, 更关注的是 第六七八条sql的执行, 按照常理来推断 tx1 会比 tx2 的事务号 小1, 在 INNODB_TRX 数据表中可以看到各个事务的详细信息 

tx1 : begin;
tx1 : update tz_test_02 set field1 = 'field1_dummy', field2 = 'field2_dummy' where id = 10;
tx1 : select * from tz_test_02 where id = 5;
tx2 : begin;
tx2 : select * from tz_test_02 where id = 5;
tx2 : update tz_test_02 set field1 = 'field1_updated', field2 = 'field2_updated' where id = 5;
tx1 : select * from tz_test_02 where id = 5;
tx2 : select * from tz_test_02 where id = 5;
tx2 : commit ;
tx1 : commit ;

 

第三条查询, rec 数据如下 

f9ed2235d873cdab36c14b0028bc2a35.png

 

rec 中数据拆解如下 

024119dad8cd9654ba3aabc9cc8bc5e4.png

 

第六条更新的处理如下, 新增记录为 insert_buf

eda4ea7d6519ce3fd9179e602288d821.png

 

第七条查询处理如下, 根据 主键的 id 这边定位到的记录为 上面 新增的更新之后的 记录信息

a45ab0262aef20b12db10de1081ea691.png

 

更新操作新增的记录信息如下, 从这里的事务号可以做一个大致的推导 

更新记录的事务是 tx2, 这里的事务编号为 44104, 因此 tx1 的事务编号为 44103

80160323bcea5f85ed1304f50d96a32a.png

 

 

判断当前记录是否对目标 ReadView 可见的方式如下, 具体的各个字段的逻辑意义可以参考 MVCC::view_open

m_low_limit_id, m_low_limit_no 表示的是当前创建 ReadView 的时候事务系统最大的事务编号 

m_up_limit_id 表示的是创建 ReadView 的时候, 除去当前事务的写视图列表 中最小的事务编号 

m_ids 表示的是创建 ReadView 的时候, 事务系统中 除去当前事务的写视图列表 

m_creator_trx_id 表示的是当前 事务id

一个关键的地方就是, 如果当前事务未产生写操作, m_creator_trx_id 为 0, 并且 INNODB_TRX 中的 trx_id 的字段数据也不准确 

所以这里的判断标准为, 如果是小于活跃的最小写事务 或者 当前事务的更新, 是直接判断为可读取的 

如果是大于 创建 ReadView 的时候的事务系统的最大的事务编号, 不可读取 

如果 没有其他的活跃的写事务列表 则可以读取目标记录

如果 事务编号 是 其他的活跃写事务 更新的, 不可读 

 

对于我们这里的场景, 更新之后的记录 对于 事务1 来说, 不可读, 因为 该记录的更新事务存在于 m_ids 列表中 

对于事务2来说, 可读, 因为该记录的更新事务 就是当前事务

f6867208a07965698d6d9b53785319a0.png

 

然后回到问题现场, 我们看一下 这里的两个事务的读写的情况, 首先看一下 tx1

m_low_limit_id, m_low_limit_no 为当前事务系统中最大的事务编号, 为 44105, 

m_up_limit_id 为 除去当前事务之外的其他写事务的最小的编号 44104

m_creator_trx_id, prebuilt->trx->id 表示当前事务的事务编号

m_ids 表示的是除去当前事务之外的其他的写事务, 这里仅仅有 tx2 编号为 44104

然后这里 rec 最新是被 tx2 更新的, 因此记录中的 trxId 为 44104, 根据上面 ReadView::changes_visiables 的相关约束, 可以知道这里 tx1 是读取不到这里最新的 rec 的 

因此这里 row_sel_build_prev_vers_for_mysql 是根据 undo log 向前回溯更老版本的记录信息

20a9aba10cfcdc366bc3707b46c2e4c6.png

 

回溯之后的记录如下, 为下面的 old_vers, 其内容和更新之前的 rec 的记录内容一样 

然后 下面的时候更新 rec, prev_rec, 然后走 row_search_mvcc 之后的流程 

然后是 根据主键迭代下一条记录, id=10, 然后 在 row_search_mvcc 的流程中 匹配不上查询条件, 返回 DB_RECORD_NOT_FOUND 跳出循环 

be48e4e024fa4763f1cd657b07533630.png

 

old_vers 的内容剖析如下, trx_id 为 44101, 这个对于当前事务 来说是可见的 如果是小于活跃的最小写事务 或者 当前事务的更新, 是直接判断为可读取的 

9dd207e308a74e2e1ff221c951bdc010.png

 

然后回到问题现场, 我们看一下 这里的两个事务的读写的情况, 首先看一下 tx2

m_low_limit_id, m_low_limit_no 为当前事务系统中最大的事务编号, 为 44105, 

m_up_limit_id 为 除去当前事务之外的其他写事务的最小的编号 44103

m_creator_trx_id, prebuilt->trx->id 表示当前事务的事务编号

m_ids 表示的是除去当前事务之外的其他的写事务, 这里仅仅有 tx2 编号为 44103

然后这里 rec 最新是被 tx2 更新的, 因此记录中的 trxId 为 44104, 根据上面 ReadView::changes_visiables 的相关约束, 可以知道这里 tx2 可以读取到这里最新的 rec 的 

a3486c68c287ba839d616b169f2be1ba.png

 

最新的记录内容拆解如下, trxId 为 44104 就是当前事务, 当前事务可读目标记录 

3e609141425f8f41d0b6b9422c36c6f0.png

 

 

可重复读

已提交读, 无脏读问题, 但是还是存在重复读的问题, 意思就是在 同一个事务中, 未更新某记录 但是多次查询该记录 得到的状态不相同

执行序列如下, 我们这里更加关心的是 id=5 的记录的更新, 更关注的是 第六八九条sql的执行, 按照常理来推断 tx1 会比 tx2 的事务号 小1, 在 INNODB_TRX 数据表中可以看到各个事务的详细信息 

tx1 : begin;
tx1 : update tz_test_02 set field1 = 'field1_dummy', field2 = 'field2_dummy' where id = 10;
tx1 : select * from tz_test_02 where id = 5;
tx2 : begin;
tx2 : select * from tz_test_02 where id = 5;
tx2 : update tz_test_02 set field1 = 'field1_updated', field2 = 'field2_updated' where id = 5;
tx2 : commit ;
tx1 : select * from tz_test_02 where id = 5;
tx2 : select * from tz_test_02 where id = 5;
tx1 : commit ;

 

我们这里着重关注 第八条 这里的查询, 因为前面的处理 和上面脏读的 case 都是一样的

m_low_limit_id, m_low_limit_no 为当前事务系统中最大的事务编号, 为 44106, 

m_up_limit_id 为 除去当前事务之外的其他写事务的最小的编号 NULL, 默认取最大的事务编号

m_creator_trx_id, prebuilt->trx->id 表示当前事务的事务编号

m_ids 表示的是除去当前事务之外的其他的写事务, 这里为空, 因为 tx2 已经提交了

然后这里 rec 最新是被 tx2 更新的, 因此记录中的 trxId 为 44104, 根据上面 ReadView::changes_visiables 的相关约束, 可以知道这里 tx2 可以读取到这里最新的 rec 的 

24910ab8865e8f05f7222384039e444d.png

 

 

幻觉读

已提交读 存在不可重复读问题, 那么就存在 幻觉读的问题

这里不再赘述, 调试这一过程 

事务1开始事务

事务1 查询 id 为 20 的记录, 发现不存在 

事务2开始事务

事务2插入 id 为 20 的记录

事务2提交事务

事务1 查询 id 为 20 的记录, 发现存在 

事务1提交

 

 

可重复读 REPEATABLE_READ

脏读

可重复读, 无脏读问题, 主要是基于 MVVC 来解决脏读的问题的

执行序列如下, 和上面已提交读解决脏读问题一样, 这里不再赘述

tx1 : begin;
tx1 : update tz_test_02 set field1 = 'field1_dummy', field2 = 'field2_dummy' where id = 10;
tx1 : select * from tz_test_02 where id = 5;
tx2 : begin;
tx2 : select * from tz_test_02 where id = 5;
tx2 : update tz_test_02 set field1 = 'field1_updated', field2 = 'field2_updated' where id = 5;
tx1 : select * from tz_test_02 where id = 5;
tx2 : select * from tz_test_02 where id = 5;
tx2 : commit ;
tx1 : commit ;

 

 

不可重复读

这个主要也是基于 MVVC 的处理, 和上面 已提交读 的差异主要是在于 ReadView 的生命周期 

已提交读 中 ReadView 这边每一次查询, 都会重新创建 ReadView, 每一次 MVCC::view_open 的时候 会从 trx_sys 中获取最新的 m_low_limit_no, m_low_limit_id, m_ids, m_up_limit_id

然后 只要有 写事务tx2 提交了, 然后 tx1 这边下一次查询的时候创建最新的 ReadView, 获取到的就是 m_low_limit_no, m_low_limit_id, m_up_limit_id 为 trx_sys->max_trx_id, 然后 m_ids 列表为空 

因此当 tx2 这边提交了事务之后, tx1 就可以读取到 tx2 的改动了 

 

然后 可重复读这边 ReadView 这边的生命周期相对较长, 是延迟到了 事务结束

因此 在该事务生命周期能够看到的数据是固定的, 一方面是创建事务的时候的快照, 另一方面是当前事务的相关调整 

 

已提交读这边每一次执行对于 ReadView 的关闭的处理, 可以看到的是 未提交读 和 已提交读 这边每一次 optimize 完成之后会关闭 ReadView

79c3e704386633bd9469a16403931769.png

 

 

然后 我们来看拿一下 可重复读 这边对于 可重复读 的问题的处理, 就是保存了一个 ReadView 的快照 

sql 执行序列如下 

tx1 : begin;
tx1 : update tz_test_02 set field1 = 'field1_dummy', field2 = 'field2_dummy' where id = 10;
tx1 : select * from tz_test_02 where id = 5;
tx2 : begin;
tx2 : select * from tz_test_02 where id = 5;
tx2 : update tz_test_02 set field1 = 'field1_updated', field2 = 'field2_updated' where id = 5;
tx2 : commit ;
tx1 : select * from tz_test_02 where id = 5;
tx2 : select * from tz_test_02 where id = 5;
tx1 : commit ;

 

我们这里关注的是 第三个查询, 第六个更新, 第八个查询 

这里第三个查询的时候, 创建的 ReadView 的快照 

m_low_limit_id, m_low_limit_no 为当前事务系统中最大的事务编号, 为 44107

m_up_limit_id 为 除去当前事务之外的其他写事务的最小的编号 NULL, 默认取最大的事务编号 44107

m_creator_trx_id, prebuilt->trx->id 表示当前事务的事务编号

m_ids 表示的是除去当前事务之外的其他的写事务, 这里为空, 因为 tx2 尚未开始

bca2043bcb7be2c0b0304fcfcd70b343.png

 

第六个更新的使用, 新增的记录信息如下, insert_buf 则是新的记录的数据 

然后 rec 中是更新之后的数据, 从上下文 或者 上面的 tx1 的事务号 可以推导出 tx2 的事务号为 47107

a6903ff3295f2ae65c6121314b7f7a96.png

 

这里可以看出新的记录事务编号为 47107, 这就是当前事务的事务编号 

736df6cd305f96829e4c0fc7e2df2840.png

 

第八个查询如下, tx1 的 ReadView 如下, 可以看到的是 和创建的时候一样

然后当前 记录的 trxId 为 47017, 然后明显是对于当前事务不可见的, 然后 需要 查看之前的版本

至此就解释了 可重复读 这边的一个具体的实现, 在事务开始的查询的地方创建的 ReadView, 而后 事务结束进行 close 

e2c4a9550a4f91c9e6f204f3f65985f2.png

 

然后事务 commit 的时候, 关闭当前事务关联的 ReadView

ee7dcc2b4e7e53feb462911d6e3523ba.png

 

 

幻觉读

在可重复读中构造 幻觉读的场景主要是基于了 mysql, select for update, select lock in share mode, insert, update, delete 是基于当前读的, 普通的无锁 select 是基于快照读 

执行序列如下

tx1 : begin;
tx1 : select * from tz_test_02;
tx2 : begin;
tx2 : INSERT INTO `test_02`.`tz_test_02`(`id`, `field1`, `field2`) VALUES (25, 'field25', '25');
tx2 : commit ;
tx1 : update tz_test_02 set field1 = 'field1_phantom', field2 = 'phantom' where id = 25;
tx1 : select * from tz_test_02;
tx1 : commit ;

 

我们这里核心关注的是 第四行的 insert, 和 第六行的 update 和 第七行的 select 

update 需要在 commit 之后, 因为 tx2 插入记录的时候在记录上面有一个 插入意向锁, tx1 update 的时候, mysql 这边会将插入意向锁升级为 行排他锁, 然后 tx2 获取 行排他锁 失败, 需要阻塞等待 

新增元素的时候, 会在元素上面增加一个 隐式锁, 但是 添加的地方 我这边没有找到

ed87db4f86e72ae3830d47b11200937e.png

 

第六行的 update, 将目标记录的 trxId 更新为 tx1 的事务编号 

1ca927bc2349b9b921070ead18151fb4.png

 

更新之后的记录信息如下, 事务编号为 47277

e05113e91880410521602ba4516c18f8.png

 

row_search_mvcc 的时候查询到目标记录, trxId 为 42477, 然后就是当前事务的更新

当前 ReadView 可读, 然后将数据 响应回去

28f30ab6359b422b4dfb8bd67cbcfbac.png

 

响应结果如下 

57670bbf997248a591e194a929e20b2d.png

 

 

串行化 SERIALIZED

所有的读操作增加读锁, 所有的写操作增加写锁, 从而保证每一条语句的执行都在一个安全的上下文 

执行序列如下, 比如 tx1 这边执行了 “select * from tz_test_02;” 之后, 会在查询的所有行上面增加 行共享锁 

然后 tx2 上面执行 “INSERT INTO” 会尝试获取 supremum 记录的行排他锁, 获取失败, 然后 阻塞等待 tx1 释放持有的锁 

tx1 : begin;
tx1 : select * from tz_test_02;
tx2 : begin;
tx2 : INSERT INTO `test_02`.`tz_test_02`(`id`, `field1`, `field2`) VALUES (25, 'field25', '25');
tx2 : commit ;
tx1 : update tz_test_02 set field1 = 'field1_phantom', field2 = 'phantom' where id = 25;
tx1 : select * from tz_test_02;
tx1 : commit ;

 

 

事务2 增加隐式锁, 事务1获取锁升级的流程

在上面 可重复读 的 幻觉读 的示例中, 我们将 tx1 的更新提前到 tx2 提交之前, 此时 tx1 的更新会阻塞住, 我们这里看一下 这个流程

执行序列如下

tx1 : begin;
tx1 : select * from tz_test_02;
tx2 : begin;
tx2 : INSERT INTO `test_02`.`tz_test_02`(`id`, `field1`, `field2`) VALUES (25, 'field25', '25');
tx1 : update tz_test_02 set field1 = 'field1_phantom', field2 = 'phantom' where id = 25;
tx2 : commit ;
tx1 : select * from tz_test_02;
tx1 : commit ;

 

第四句 sql 插入记录, 新增元素的时候, 会在元素上面增加一个 隐式锁, 但是 添加的地方 我这边没有找到

985447fe22f0ab7c147b16de6fc08fae.png

 

第五句 update, 导致的 隐式锁 升级为 显式锁

从上下文可以知道, 这里是升级成为了一个 行排他锁

1d1cc59f9a4c6dc75e5a59eccfd642e8.png

 

这里当前 update 操作, 也是申请 该记录的行排他锁, 该行排他锁已经被 tx2 持有, 会被 tx2 阻塞 

054a83635893a164fb2b60cd823dce7d.png

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/939640.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【FFmpeg】解封装 ① ( 封装与解封装流程 | 解封装函数简介 | 查找码流标号和码流参数信息 | 使用 MediaInfo 分析视频文件 )

文章目录 一、解封装1、封装与解封装流程2、解封装 常用函数 二、解封装函数简介1、avformat_alloc_context 函数2、avformat_free_context 函数3、avformat_open_input 函数4、avformat_close_input 函数5、avformat_find_stream_info 函数6、av_read_frame 函数7、avformat_s…

Nginx(Linux之Ubuntu)

1.1.什么是Nginx Nginx(发音为"engine x")是由俄罗斯开发者Igor Sysoev创建的一款轻量级、高性能的Web服务器。它首次发布于2004年,如今已成为全球最受欢迎的Web服务器之一。Nginx以其卓越的性能和灵活性而闻名,适用于…

使用Docker启用MySQL8.0.11

目录 一、Docker减小镜像大小的方式 1、基础镜像选择 2、减少镜像层数 3、清理无用文件和缓存 4、优化文件复制(COPY和ADD指令) 二、Docker镜像多阶段构建 1、什么是dockers镜像多阶段构建 1.1 概念介绍 1.2 构建过程和优势 2、怎样在Dockerfil…

【微信小程序开发 - 3】:项目组成介绍

文章目录 项目组成介绍项目的基本组成结构小程序页面的组成部分JSON配置文件的作用app.json文件project.config.json文件sitemap.json文件页面的 .json 配置文件新建小程序页面修改项目首页 XWML模板XWML 和 HTML 的区别 WXSS样式WXSS 和 CSS 的区别 .js文件 项目组成介绍 项目…

springboot的项目创建和常用注解

创建springboot项目&#xff1a; 首先更改一下url&#xff0c;点击小齿轮改成https://start.aliyun.com/ 首先在选模块的时候选上SpringWeb&#xff0c;然后jdk1.8对应的springboot版本是2.6.13或者2.7.6 pom.xml: 用1.8的jdk&#xff0c;mybatis的包版本不能太高 <!-- …

flask_socketio 以继承 Namespace方式实现一个网页聊天应用

点击进入上一篇&#xff0c;可作为参考 实验环境 python 用的是3.11.11 其他环境可以通过这种方式一键安装&#xff1a; pip install flask3.1.0 Flask-SocketIO5.4.1 gevent-websocket0.10.1 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple pip list 详情如下&am…

笔记本重装系统教程【详细教程】

一、装机前说明 各位有装机需求的伙伴&#xff0c;请根据自己的电脑配置选择合适操作系统&#xff0c;可以实现自己装机的伙伴&#xff0c;相信大家这点可以确认好。 ———————————————————————— 我的配置&#xff1a; 我的电脑是联想拯救者lenovoY7000…

uniapp入门 01创建项目模版

0安装 hbuilder x 标准版 1.创建模版工程 2.创建官方 案例工程 index.uvuewen 文件解析 <!-- 模版 标签 --> <template><view></view></template><!-- 脚本 --> <script>export default {data() {return {}},onLoad() {},methods:…

ARCGIS国土超级工具集1.2更新说明

ARCGIS国土超级工具集V1.2版本&#xff0c;功能已增加至47 个。在V1.1的基础上修复了若干使用时发现的BUG&#xff0c;新增了"矢量分割工具"菜单&#xff0c;同时增加及更新了了若干功能&#xff0c;新工具使用说明如下&#xff1a; 一、勘测定界工具栏更新界址点成果…

Vue3源码笔记阅读1——Ref响应式原理

本专栏主要用于记录自己的阅读源码的过程,希望能够加深自己学习印象,也欢迎读者可以帮忙完善。接下来每一篇都会从定义、运用两个层面来进行解析 定义 运用 例子:模板中访问ref(1) <template><div>{{str}}</div> </template> <script> impo…

[react] 优雅解决typescript动态获取redux仓库的类型问题

store.getState()是可以获取总仓库的 先拿到函数的类型 再用ReturnType<T> 它是 TypeScript 中的一个内置条件类型&#xff0c;用于获取某个函数类型 T 的返回值类型 代码 // 先拿总仓库的函数类型type StatefuncType typeof store.getState;//再拿函数类型T的返回值类…

【Qt】QWidget中的常见属性及其功能(一)

目录 一、 enabled 例子&#xff1a; 二、geometry 例子&#xff1a; window fram 例子 &#xff1a; 四、windowTiltle 五、windowIcon 例子&#xff1a; qrc机制 创建qrc文件 例子&#xff1a; qt中的很多内置类都是继承自QWidget的&#xff0c;因此熟悉QWidget的…

R语言的字符串操作

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言医学数据分析实践-R语言的数据结构-CSDN博客 在R语言中&#xff0c;字符串是一种表示文本数据的数…

webGL硬核知识:图形渲染管渲染流程,各个阶段对应的API调用方式

一、图形渲染管线基础流程概述 WebGL 的图形渲染管线大致可分为以下几个主要阶段&#xff0c;每个阶段都有其特定的任务&#xff0c;协同工作将 3D 场景中的物体最终转换为屏幕上呈现的 2D 图像&#xff1a; 顶点处理&#xff08;Vertex Processing&#xff09;阶段&#xff1…

《深入浅出Apache Spark》系列⑤:Spark SQL的表达式优化

导读&#xff1a;随着数据量的快速增长&#xff0c;传统的数据处理方法难以满足对计算速度、资源利用率以及查询响应时间的要求。为了应对这些挑战&#xff0c;Spark SQL 引入了多种优化技术&#xff0c;以提高查询效率&#xff0c;降低计算开销。本文从表达式层面探讨了 Spark…

创建项目以及本地仓库和远程仓库并上传项目

创建项目以及本地仓库和远程仓库并上传项目 其详细流程如下&#xff1a; 1、本地创建项目 2、创建本地仓库&#xff08;若使用idea在创建项目时选择了创建.git本地仓库&#xff0c;则此步骤省略&#xff09; 进入到你需要上传的项目的目录下&#xff0c;右键找到Git Bah He…

快速解决oracle 11g中exp无法导出空表的问题

在一些生产系统中&#xff0c;有些时候我们为了进行oracle数据库部分数据的备份和迁移&#xff0c;会使用exp进行数据的导出。但在实际导出的时候&#xff0c;我们发现导出的时候&#xff0c;发现很多空表未进行导出。今天我们给出一个快速解决该问题的办法。 一、问题复现 我…

MySQL八股-MVCC入门

文章目录 当前读&#xff08;加锁&#xff09;快照读&#xff08;不加锁&#xff09;MVCC隐藏字段undo-log版本链A. 第一步B.第二步C. 第三步 readview MVCC原理分析RCA. 先来看第一次快照读具体的读取过程&#xff1a;B. 再来看第二次快照读具体的读取过程: RR隔离级别 当前读…

【已解决】启动此实时调试器时未使用必需的安全权限。要调试该进程,必须以管理员身份运行此实时调试器。是否调试该进程?

【已解决】启动此实时调试器时未使用必需的安全权限。要调试该进程&#xff0c;必须以管理员身份运行此实时调试器。是否调试该进程? 目录一、前言二、具体原因三、解决方法 目录 报错截图 一、前言 进行应用程序开发时&#xff0c;需要对w3wp进行附加调试等场景&#xff…

基于Qt的登陆界面设计

目标 自由发挥登录界面的应用场景&#xff0c;实现一个登录窗口的界面。 要求&#xff1a;每行代码都要有注释 代码 // 设置窗口大小为600x400像素 this->resize(600,400); // 设置窗口标题为"TheWitcher 巫师3&#xff1a;狂猎" this->setWindowTitle(&qu…