MySQL 是如何实现四大隔离级别的?

MySQL 是如何实现四大隔离级别的?

在mvcc下,mysql中用到的锁还是共享锁和排他锁么?如果是的话,那么是怎样结合锁和mvcc来实现rc和rr隔离级别的呢?还有mysql中在ru隔离级别下,两个事务同时读取数据对象A,当事务1修改A之后,事务2可以立即读到修改数据,但是在1提交之前,2想修改A会被阻塞,据说ru下没有mvcc。那么是怎么实现出这样的效果的呢?

以下是个人推测:
行锁:
read uncommitted:
事务修改数据加排他锁,改完释放排它锁,加共享锁,直到提交事务释放。
事务读取数据读永远读最高版本数据。

read committed:
事务修改数据加排它锁,直到事务提交释放。
事务读取数据永远读最高版本数据。

repeatable read :
事务修改数据加排它锁,直到事务提交释放。
事务读取数据版本号小于等于事务版本号的数据。

serializablr:
不使用mvcc。
事务修改数据加排他锁,读取数据加共享锁,直到提交释放。(低并发,极易死锁)

这是个人根据测试结果进行猜测的。望大神指点更正!

在这里插入图片描述

引子

众所周知,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。提到事务,你肯定立马脱口而出 ACID(原子性 Atomicity、一致性 Consistency、隔离性 Isolation、持久性 Durability)

当数据库上有多个事务同时执行的时候,就可能出现一些并发一致性问题:丢失更新(Last To Modify)、脏读(Dirty Read)、不可重复读(Unrepeatable Read)、幻读(Phantom Read)

那么为了解决这些问题,就有了 “隔离级别” 的概念。

万事终归有利有弊,隔离级别越高,隔离得越严实,并发一致性问题就越少,那么相应的数据库付出的性能代价也就越大。所以,很多时候,我们都要在这二者之间寻找一个平衡点。

四种并发一致性问题

丢失更新 Last To Modify

丢失更新非常好理解,简单来说其就是一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据的不一致。

举个例子:

1)事务 T1 将行记录 r 更新为 v1,但是事务 T1 并未提交

2)与此同时,事务 T2 将行记录 r 更新为 v2,事务 T2 未提交

3)事务 T1 提交

4)事务 T2 提交

如下图所示,显然,事务 T1 丢失了自己的修改。

img

但是,事实上,这种情况准确来讲并不会发生。

因为我们说过对于行进行更新操作的时候,需要对行或其他粗粒度级别的对象加锁,因此当事务 T1 修改行 r 但是没提交的时候,事务 T2 对行 r 进行更新操作的时候是会被阻塞住的,直到事务 T1 提交释放锁。

所以,从数据库层面来讲,数据库本身是可以帮助我们阻止丢失更新问题的发生的

不过,在真实的开发环境中,我们还经常会遇到逻辑意义上的丢失更新。

举个例子:

1)事务 T1 查询一行数据 r,放入本地内存,并显示给一个用户 User1
2)事务 T2 也查询该行数据,并将取得的数据显示给另一个用户 User2
3)User1 修改了行记录 r 为 v1,更新数据库并提交
4)User2 修改了行记录 r 为 v2,更新数据库并提交

显然,最终这行记录的值是 v2,User1 的更新操作被 User2 覆盖掉了,丢失了他的修改。

在这里插入图片描述

可能还是云里雾里,我来举个更现实点的例子吧,一个部门共同查看一个在线文档,员工 A 发现自己的性别信息有误,于是将其从 “女” 改成了 “男”,就在这时,HR 也发现了员工 A 的部门信息有误,于是将其从 ”测试“ 改成了 ”开发“,然后,员工 A 和 HR 同时点了提交,但是 HR 的网络稍微慢一点,再次刷新,员工 A 就会发现,擦,我的性别怎么还是 ”女“?

在这里插入图片描述

脏读 Dirty Read

所谓脏读,就是说一个事务读到了另外一个事务中的 “脏数据”,脏数据就是指事务未提交的数据

如下图所示,在事务并没有提交的前提下,事务 T1 中的两次 SELECT 操作取得了不同的结果:
在这里插入图片描述
注意,如果想要再现脏读这种情况,需要把隔离级别调整在 Read UnCommitted(读取未提交)。所以事实上脏读这种情况基本不会发生,因为现在大部分数据库的隔离级别都至少设置成 READ COMMITTED

不可重复读 Unrepeatableread

不可重复读是指在一个事务内多次读取同一数据集合。在这个事务还没有结束时,另外一个事务也访问该同一数据集合,并做了一些修改操作。因此,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。

举个例子:事务 T1 读取一行数据 r,T2 将该行数据修改成了 v1。如果 T1 再次读取这行数据,此时读取的结果和第一次读取的结果是不同的

在这里插入图片描述

不可重复读和脏读的区别是:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但是其违反了事务一致性的要求。

幻读 Phantom Read

幻读本质上是属于不可重复读的一种情况,区别在于,不可重复读主要是针对数据的更新(即事务的两次读取结果值不一样),而幻读主要是针对数据的增加或减少(即事务的两次读取结果返回的数量不一样)

举个例子:事务 T1 读取某个范围的数据,事务 T2 在这个范围内插入了一些新的数据,然后 T1 再次读取这个范围的数据,此时读取的结果比第一次读取的结果返回的记录数要多
在这里插入图片描述

四种事务隔离级别

SQL 标准定义了四种越来越严格的事务隔离级别,用来解决我们上述所说的四种事务的并发一致性问题。

1)READ UNCOMMITTED 读取未提交:一个事务还没提交时,它做的变更就能被别的事务看到上面提到过,数据库本身其实已经具备阻止丢失更新的能力,也就是说,即使是最低的隔离级别也可以阻止丢失更新问题。所以:这个隔离级别可以阻止 丢失更新

2)READ COMMITTED 读取已提交:一个事务提交之后,它做的变更才会被其他事务看到。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。这个隔离级别可以阻止 丢失更新 + 脏读

3)REPEATABLE READ 可重复读(InnoDB 存储引擎默认的隔离级别):保证在同一个事务中多次读取同一数据的结果是一样的。当然了,在可重复读隔离级别下,未提交变更对其他事务也是不可见的。

书中就是这么解释的,好像也挺通俗易懂的,那为了方便下面的行文,我再给一个更简单的解释:
可重复读就是:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。或者简单来说,事务在执行期间看到的数据前后是一致的。

这个隔离级别可以阻止 丢失更新 + 脏读 + 不可重复读

4)SERIALIZABL 可串行化:顾名思义,强制事务串行执行,对于同一行记录,“写” 会加 “写锁”,“读” 会加 “读锁”,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。这样多个事务互不干扰,不会出现并发一致性问题

这个隔离级别可以阻止 丢失更新 + 脏读 + 不可重复读 + 幻读

在这里插入图片描述

可以看到四种隔离级别能阻止的并发一致性问题越来越多,但并不代表越高的隔离级别就越好,因为事务隔离级别越高,数据库付出的性能代价也就相应地越大。

另外,多提一嘴,InnoDB 存储引擎在 REPEATABLE READ 可重复读的隔离级别下,使用 Next-Key Lock 锁的算法避免了幻读的产生, 具体可以看这篇文章 幻读为什么会被 MySQL 单独拎出来解决?。也就是说,InnoDB 存储引擎在其默认的 REPEATABLE READ 事务隔离级别下就已经能完全保证事务的隔离性要求了,即达到了 SQL 标准的 SERIALIZABLE 隔离级别。

举个例子,看下图,我们来看看在不同的隔离级别下,事务 A 对同一个字段的查询会得到哪些不同的返回结果:
在这里插入图片描述
1)READ UNCOMMITTED 读取未提交:V1 V2、V3 都是 2。事务 B 虽然还没有提交,但是修改的结果结果已经被 A 看到了

2)READ COMMITTED 读取已提交:V1 是 1,然后事务 B 对字段的修改提交了,能被 A 看到,所以,V2 V3 的值都是 2

3)REPEATABLE READ 可重复读:V1 V2 是 1,V3 是 2。回想下这句话你就懂了:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的

4)SERIALIZABL 可串行化:事务 B 执行 “将字段 a 的值改为 2” 的时候会被锁住。直到事务 A 提交后,事务 B 才可以继续执行。所以从事务 A 的角度看, V1 V2 的值是 1,V3 的值是在事务 2 提交后的,所以 V3 是 2。

四种隔离级别的具体实现

读取未提交和可串行化的实现没什么好说的,一个是啥也不干,一个是直接无脑加锁避开并行化 让你啥也干不成。

重头戏就是读取已提交和可重复读是如何实现的。这就是我们要说的 MVCC 了,也就是面试中的超级高频题。

我先来简单说一下,对于这两个隔离级别,数据库会为每个事务创建一个视图 (ReadView),访问的时候以视图的逻辑结果为准:

  • 在 “读取已提交” 隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的
  • 在 “可重复读” 隔离级别下,这个视图是在事务启动时就创建的,整个事务存在期间都用这个视图(这就是为什么说在可重复读隔离级别下,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的)

那么问题了就来了,已经执行了这么多的操作,事务该如何重新回到之前视图记录的状态?数据库会通过某种手段记录这之间执行的种种操作吗?

这就是 undo log 版本链做的事

undo log 版本链

在 MySQL 中,每条记录在更新的时候都会同时记录一条回滚操作(也就是 undo log),当前记录上的最新值,通过回滚操作,都可以得到前一个状态的值。

简单理解,undo log 就是每次操作的反向操作,比如比如当前事务执行了一个插入 id = 100 的记录的操作,那么 undo log 中存储的就是删除 id = 100 的记录的操作。

也就是说,B+ 索引树上对应的记录只会有一个最新版本,但是 InnoDB 可以根据 undo log 得到数据的历史版本。同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)

在这里插入图片描述
那么,还有个问题,undo log 是如何和某条行记录产生联系的呢?换句话说,我怎么能通过这条行记录找到它拥有的 undo log 呢?

具体来说,InnoDB 存储引擎中每条行记录其实都拥有两个隐藏的字段:trx_id 和 roll_pointer:

  • trx_id 就是最近更新这条行记录的事务 ID
  • roll_pointer 就是指向之前生成的 undo log 的指针

掏出我们的 user 表,来举个例子,假设 id = 100 的事务 A 插入一条行记录(id = 1, username = “Jack”, age = 18),那么,这行记录的两个隐藏字段 trx_id = 100 和 roll_pointer 指向一个空的 undo log,因为在这之前并没有事务操作 id = 1 的这行记录。如图所示:

在这里插入图片描述

然后,id = 200 的事务 B 修改了这条行记录,把 age 从 18 修改成了 20,于是,这条行记录的 trx_id 就变成了 200,rooll_pointer 就指向事务 A 生成的 undo log :

在这里插入图片描述

接着,id = 300 的事务 C 再次修改了这条行记录,把 age 从 20 修改成了 30,如下图:

在这里插入图片描述

可以看到,每次修改行记录都会更新 trx_id 和 roll_pointer 这两个隐藏字段,之前的多个数据快照对应的 undo log 会通过 roll_pointer 指针串联起来,从而形成一个版本链

那么问题又来了,一个记录会被一堆事务进行修改,一个记录上会存在许许多多的 undo log,**那么对于其中某一个事务来说,它能看见哪些 undo log?**或者说,对于其中某一个事务来说,它能够根据哪些 undo log 执行回滚操作?

让我们来详细解释一下这个视图(ReadView)机制

ReadView 机制

ReadView 机制就是用来判断当前事务能够看见哪些版本的,一个 ReadView 主要包含如下几个部分:

  • m_ids:生成 ReadView 时有哪些事务在执行但是还没提交的(称为 “活跃事务”),这些活跃事务的 id 就存在这个字段里
  • min_trx_id:m_ids 里最小的值
  • max_trx_id:生成 ReadView 时 InnoDB 将分配给下一个事务的 ID 的值(事务 ID 是递增分配的,越后面申请的事务 ID 越大)
  • creator_trx_id:当前创建 ReadView 事务的 ID

接下来,再掏出 user 表,通过一个例子来理解下 ReaView 机制是如何做到判断当前事务能够看见哪些版本的:

假设表中已经被之前的事务 A(id = 100)插入了一条行记录(id = 1, username = “Jack”, age = 18),如图所示:
在这里插入图片描述
接下来,有两个事务 B(id = 200) 和 C(id = 300)过来并发执行,事务 B 想要更新(update)这行 id = 1 的记录,而事务 C(select)想要查询这行数据,这两个事务都执行了相应的操作但是还没有进行提交:
在这里插入图片描述

如果现在事务 B 开启了一个 ReadView,在这个 ReadView 里面:

  • m_ids 就包含了当前的活跃事务的 id,即事务 B 和事务 C 这两个 id,200 和 300
  • min_trx_id 就是 200
  • max_trx_id 是下一个能够分配的事务的 id,那就是 301
  • creator_trx_id 是当前创建 ReadView 事务 B 的 id 200

在这里插入图片描述
现在事务 B 进行第一次查询(select 操作不会生成 undo log 的哈),会把这行记录的隐藏字段 trx_id 和 ReadView 的 min_trx_id 进行下判断,此时,发现 trx_id 是 100,小于 ReadView 里的 min_trx_id(200),这说明在事务 B 开始之前,修改这行记录的事务 A 已经提交了,所以开始于事务 A 提交之后的事务 B、是可以查到事务 A 对这行记录的更新的。

row.trx_id < ReadView.min_trx_id

在这里插入图片描述
接着事务 C 过来修改这行记录,把 age = 18 改成了 age = 20,所以这行记录的 trx_id 就变成了 300,同时 roll_pointer 指向了事务 C 修改之前生成的 undo log:
在这里插入图片描述
那这个时候事务 B 再次进行查询操作,会发现这行记录的 trx_id(300)大于 ReadView 的 min_trx_id(200),并且小于 max_trx_id(301)。

row.trx_id > ReadView.min_trx_id && row.trx_id < max_trx_id

这说明一个问题,就是更新这行记录的事务很有可能也存在于 ReadView 的 m_ids(活跃事务)中。所以事务 B 会去判断下 ReadView 的 m_ids 里面是否存在 trx_id = 300 的事务,显然是存在的,这就表示这个 id = 300 的事务是跟自己(事务 B)在同一时间段并发执行的事务,也就说明这行 age = 20 的记录事务 B 是不能查询到的。

在这里插入图片描述
既然无法查询,那该咋整?事务 B 这次的查询操作能够查到啥呢?

没错,undo log 版本链

这时事务 B 就会顺着这行记录的 roll_pointer 指针往下找,就会找到最近的一条 trx_id = 100 的 undo log,而自己的 id 是 200,即说明这个 trx_id = 100 的 undo log 版本必然是在事务 B 开启之前就已经提交的了。所以事务 B 的这次查询操作读到的就是这个版本的数据即 age = 18。

通过上述的例子,我们得出的结论是,通过 undo log 版本链和 ReadView 机制,可以保证一个事务不会读到并发执行的另一个事务的更新。

那自己修改的值,自己能不能读到呢?

这当然是废话,肯定可以读到呀。上面的例子我们只涉及到了 ReadView 中的前三个字段,而 creator_trx_id 就与自己读自己的修改有关,所以这里还是图解出来让大家更进一步理解下 ReadView 机制:

假设事务 C 的修改已经提交了,然后事务 B 更新了这行记录,把 age = 20 改成了 age = 66,如下图所示:
在这里插入图片描述
然后,事务 B 再来查询这条记录,发现 trx_id = 200 与 ReadView 里的 creator_trx_id = 200 一样,这就说明这是我自己刚刚修改的啊,当然可以被查询到。

row.trx_id = ReadView.creator_trx_id

在这里插入图片描述

那如果在事务 B 的执行期间,突然开了一个 id = 500 的事务 D,然后更新了这行记录的 age = 88 并且还提交了,然后事务 B 再去读这行记录,能读到吗?
在这里插入图片描述

答案是不能的。

因为这个时候事务 B 再去查询这行记录,就会发现 trx_id = 500 大于 ReadView 中的 max_trx_id = 301,这说明事务 B 执行期间,有另外一个事务更新了数据,所以不能查询到另外一个事务的更新。

row.trx_id > ReadView.max_trx_id

在这里插入图片描述

那通过上述的例子,我们得出的结论是,通过 undo log 版本链和 ReadView 机制,可以保证一个事务只可以读到该事务自己修改的数据或该事务开始之前的数据。

面试官:讲一下数据库的四种隔离级别,以及具体的实现
回答:数据库的四种隔离级别主要是用来解决四种并发一致性问题的,隔离级别越高,能够处理的并发一致性问题越多,相应的数据库付出的性能代价也就越高。最低的隔离级别是读取未提交,一个事务还没提交时,它做的变更就能被别的事务看到:可以解决丢失更新问题(所谓丢失更新问题,就是指一个事务的更新操作会被另一个事务的更新操作所覆盖);然后是读取已提交,一个事务提交之后,它做的变更才会被其他事务看到:可以解决丢失更新和脏读问题(所谓脏读,就是一个事务读到了另外一个事务未提交的数据);然后是 InnoDB 默认的隔离级别可重复读,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的:可以解决丢失更新、脏读和不可重复读问题(所谓不可重复读,就是指第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据是不一样的)。另外,InnoDB 的这个默认隔离级别,会通过 Next-Lock key 来解决幻读问题,所以其实是可以达到 SQL 标准的可串行化隔离级别的;最后是可串行化,强制事务串行执行,对于同一行记录,“写” 会加 “写锁”,“读” 会加 “读锁”,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。这样可以避免并发一致性问题,解决丢失更新、脏读、不可重复读和幻读问题(所谓幻读,和不可重复读差不多,不过幻读侧重于记录数量的增减,不可重复读侧重于记录的修改)对于读取已提交和可重复读这两个隔离级别来说,其底层实现就是多版本并发控制 MVCC。具体来说,对于这两个隔离级别,数据库会为每个事务创建一个视图 (ReadView),访问的时候以视图的逻辑结果为准。通过 undo log 版本链使得事务可以回滚到视图记录的状态。而这两个隔离级别的区别就在于,它们生成 ReadView 的时机是不同的:- 在 “读取已提交” 隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的- 在 “可重复读” 隔离级别下,这个视图是在事务启动时就创建的,整个事务存在期间都用这个视图

转载:https://www.zhihu.com/question/263820564

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux命令 移动/复制文件/目录到指定目录下

1、同一个服务器下复制文件或文件夹 1.1 复制文件 复制文件&#xff1a;把1.txt 复制到根目录下的sbin目录 cp 文件名&#xff08;可带路径&#xff09;目标路径&#xff08;带路径&#xff09;如&#xff1a;cp 1.txt ~/sbin/1,2 复制目录 复制目录&#xff1a;把relea…

c mysql web开发实例教程_Web开发(六)MySql

数据库简介数据库(DB)数据库(database&#xff0c;DB)是指长期存储在计算机内的&#xff0c;有组织&#xff0c;可共享的数据的集合。数据库中的数据按一定的数学模型组织、描述和存储&#xff0c;具有较小的冗余&#xff0c;较高的数据独立性和易扩展性&#xff0c;并可为各种…

Git——工作中使用命令详解

1、Linux常用命令 cd&#xff1a;改变目录cd…&#xff1a;返回上级目录pwd&#xff1a;显示当前目录clear&#xff1a;清屏ls&#xff1a;显示当前目录所有文件touch&#xff1a;添加文件rm&#xff1a;删除文件mkdir&#xff1a;新建文件夹rm -r&#xff1a;删除文件夹mv&am…

Java中常见null简析

对于每一个Java程序员来说,null肯定是一个让人头痛的东西,今天就来总结一下Java中关于null的知识。 1.null不属于任何类型,可以被转换成任何类型,但是用instanceof永远返回false. 2.null永远不能和八大基本数据类型进行赋值运算等,否则不是编译出错,就是运行出错. 3.null可以…

Chrome浏览器F5和ctrl+F5的区别

一、正常重新加载&#xff08;F5&#xff0c;Ctrl R&#xff0c;在地址栏回车&#xff0c;点击链接&#xff09; 本节中的操作&#xff1a;根据缓存的缓存策略&#xff0c;进行处理。如果缓存没过期&#xff0c;就不向浏览器发请求&#xff0c;而是直接使用缓存。 F5或Contr…

mysql 自动生成mapper_自动生成实体类、Mapper、Mapper.xml文件

自动生成实体类、Mapper、Mapper.xml文件搭建Spring Boot Mysql MyBatis 项目核心配置pom.xml创建表配置文件生成文件结果项目结构搭建Spring Boot Mysql MyBatis 项目idea 可直接创建相应的项目及配置核心配置pom.xmlmysqlmysql-connector-java5.1.38org.springframework.…

使用Postman进行简单压力测试

使用Postman可以对服务端接口进行简单的压力测试&#xff0c;步骤如下&#xff1a; 1.配置好一个请求接口&#xff0c;保存在一个collection中&#xff1b; 2.点击Tests&#xff0c;添加断言检查点&#xff1b; 3.点击Runner按钮&#xff0c;打开Collection Runner界面&#…

mysql取消主从配置_mysql主从配置

搭建环境&#xff1a;master 192.168.127.131slave 192.168.127.128主从配置的前提&#xff1a;两个数据库的数据需要一模一样所以我们&#xff1a;在主上面建立一个数据库 在这里我们用mysql备份一下mysqldump db1 >123.sql (备份)在主上面建立一个数据库db1需要登录数据…

利用Java zip进行对文件的压缩和解压

利用Java JDK自带 进行对文件的压缩和解压 实现一个文件的zip压缩&#xff0c;过程可以简单地表示为&#xff1a; ZipEntry:表示 ZIP 文件条目 构造方法: public ZipEntry(String name) 可以用文件的相对路径来构造ZipEntry对象 ZipOutputStream&#xff1a; ZIP 文件格式…

mysql数据库设计教材_mySQL教程 第1章 数据库设计

E-R设计很多同学在学SQL语句时&#xff0c;觉得非常困难&#xff0c;那是因为你在学一个你根本不了解的数据库&#xff0c;数据库中的表不是你设计的&#xff0c;表与表之间的关系你不明白。因此在学SQL语句之前&#xff0c;先介绍一下数据库设计。下面举例说明数据库设计&…

谷歌浏览器Network详解

Network用F12打开后&#xff0c;出现以下页面。5个部分分别讲解。 控制器过滤器时间轴资源内容资源概况 1.控制器 Preserve log:页面刷新也不会清空请求 Disable cache:停用浏览器缓存 Online:有网 Fast 3G、Slow 3G:自定义网速 Offline:离线模拟 2.过滤器 2.1按字符串过…

mysql5.7.14安装版_MySql5.7.14安装教程详解(解压版)_MySQL

下面进入正式的教程&#xff1a;第一步&#xff1a;下载最近的MySQL文件并且解压&#xff1a;下载最新版的MySQL–mysql-5.7.12下载地址将下载到的文件解压缩到自己喜欢的位置&#xff0c;例如我自己的位置是D:\MySQL\mysql-5.7.12-winx64第二步&#xff1a;配置环境变量这里不…

Java main方法_解释Java中的main方法,及其作用_一个java文件中可包含多个main方法

public static void main(String[] args) {}或者 public static void main(String args[]) {}main方法是我们学习Java语言学习的第一个方法&#xff0c;也是每个java使用者最熟悉的方法,每个Java应用程序都必须有且仅有一个main方法。在eclipse里可以使用输入main&#xff0c;…

端口号被占用:Disconnected from the target VM, address: ‘127.0.0.1:XXXX‘, transport: ‘socket‘

debug启动Spring boot项目的时候&#xff0c;项目没有启动起来。log最后一行&#xff0c;显示Disconnected from the target VM, address: ‘127.0.0.1:XXXX’, transport: ‘socket’。 解决方式&#xff01;&#xff01;&#xff01; 1、看看是谁占用了我的端口号&#xff…

Linux系统tab自动补全快捷键的时候显示cannot create temp file for here-document: No space left on device解决方案

登陆linux系统之后&#xff0c;使用tab自动补全快捷键的时候显示&#xff1a;cannot create temp file for here-document: No space left on device。 原因&#xff1a;磁盘满了&#xff0c;不能创建临时文件。 解决方法&#xff1a;&#xff08;逐级查看占用空间过多的目录…

python画二维数组散点图_2个numpy二维数组的散点图

IIUC,你不需要zip步骤:s (arr1.ravel(), arr2.ravel())plt.scatter(*s)plt.show()或者,你也可以通过策划arr1和arr2:plt.scatter(arr1, arr2)plt.show()原因是,通过压缩,可以创建许多坐标元组:>>> list(zip(*s))[(0.5233576831070681, 0.3622905772322086), (0.67714…

双表联查mysql_MySQL的双表多表联查

最近在做EC-Mall的二次开发&#xff0c;遇到这么一个需求&#xff0c;将挂件单独显示成一个页面。由于EC-Mall的挂件是用数据模块模块类库的方式进行的&#xff0c;就是使用类似smarty的形式。而单独一个页面的话&#xff0c;数据读取需要自己写SQL语句。 现在的问题是&#xf…

Linux中的通配符

Linux中的通配符 Linux中的通配符 *匹配任意长度的任意字符&#xff0c;可以没有?匹配任意单个字符&#xff0c;至少有1个[ ]匹配指定字符范围内的任意单个字符[a-z,A-Z,0-9]匹配所有数字和字母[a-z]匹配a-z中的一个[A-Z]匹配A-Z中的一个[a-Z]匹配所有大小写字母[:upper:]所…

mysql区间段_解决针对MySQL中对于某一个区间段范围的数据更新的情况

(1)在使用更新update的过程中&#xff0c;我们可能会想要更新比如id段在某一个指定范围内的数据&#xff0c;如果我们是想要更新前面多少行的数据的话可以直接&#xff1a;UPDATE tb_name SET column_name‘value‘ ORDER BY id ASC LIMIT 20;比如我想要把下面的这个员工信息表…

SpringBoot实现执行sql语句打印到控制台

SpringBoot实现执行sql语句打印到控制台 1.简介 每当写完持久化语句时肯定免不了要查漏补缺一波。这里就可以将执行的sql打印到控制台来检查sql语句哪里出了问题。 2.配置 配置非常简单&#xff0c;只需要在配置文件中设置下mapper日志级别就可以了 application-test.prop…