Mysql之性能优化分析

news2025/7/30 18:34:47

一、避免死锁

1.1、导致mysql死锁的要素

1、两个或者两个以上事务。
2、锁资源只能被同一个事务持有或者多个事务竞争的锁是不兼容的,比如排他锁和共享锁、排他锁和排他锁。
3、每个事务都已经持有锁并且申请新的锁。
4、事务之间因为持有锁和申请锁导致彼此循环等待。

1.2、死锁演示

-- 事务1中执行
begin; 
select * from user_innodb where id=3 for update;

-- 事务2中执行
begin; 
delete from user_innodb where id=4;

-- 事务1中执行
update user_innodb set name='haoya' where id=4;

-- 事务2中执行
delete from user_innodb where id=3;

在上述脚本运行后,会在第一个事务中看到下面这样的日志

update user_innodb set name='haoya' where id=4
> 1213 - Deadlock found when trying to get lock; try restarting
transaction
> 时间: 2.475s

Mysql立刻检测到了死锁,并且事务1马上退出了。
为什么可以直接检测到呢?是因为死锁的发生需要满足一定的条件,所以在发生死锁时,InnoDB一般都能通过算法(wait-for graph)自动检测到。

1.3、事务竞争锁的超时时间

另外还有一个要注意的点,就是事务竞争锁的时候,如果发现当前有事务正在持有锁,那么它不会一直等下去。默认情况下,它会等待50s的时间,如果50s还没有办法竞争到锁,则直接释放锁资源。

-- 事务1中执行
begin; 
select * from user_innodb where id=3 for update;

-- 事务2中执行
begin; 
select * from user_innodb where id=3 for update;

上面这个的执行结果如下:

select * from user_innodb where id=3 for update
> 1205 - Lock wait timeout exceeded; try restarting transaction
> 时间: 51.011s

事务竞争锁超时的时间,是通过下面这个属性来控制的

show VARIABLES like 'innodb_lock_wait_timeout';

所以,一个事务的锁的释放,有三种情况:

  1. 事务结束(commit/rollback)
  2. 客户端连接断开
  3. 事务竞争锁超时(50s)

1.4、查看锁的日志

如果我们需要定位当前数据库吞吐量下降的原因是否是锁竞争或者死锁导致的,应该怎么去判断呢?
在Mysql中提供了一些属性,可以看到整个数据库锁的使用情况。

show status like 'innodb_row_lock_%';

在这里插入图片描述
上述参数说明:
Innodb_row_lock_current_waits:当前正在等待锁定的数量;
Innodb_row_lock_time :从系统启动到现在锁定的总时间长度,单位ms;
Innodb_row_lock_time_avg :每次等待锁的平均时间;
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间;
Innodb_row_lock_waits :从系统启动到现在总共等待的次数;

上面只是一个总的信息,如果想看到更加详细的数据,Mysql提供了下面几个命令:

  • 查看当前运行的所有事务 ,还有具体的SQL语句;
select * from information_schema.INNODB_TRX;
  • 查看处于锁等待的详细信息
select * from sys.innodb_lock_waits; 
  • 查看正在处理中的事务
select * from information_schema.PROCESSLIST p where p.state<>'';
-- 锁定数据查询
select * from performance_schema.data_locks;

基于这些操作命令,可以定位到死锁的源头,比如select * from sys.innodb_lock_waits;这个语句中的最后两列,提供了两个属性:
sql_kill_blocking_query kill掉这个query语句的线程
sql_kill_blocking_connection kill条这个阻塞的连接
通过提供的参考命令,可以直接把锁等待的线程终止。
也可以通过select * from information_schema.INNODB_TRX;这个语句中查询到的trx_mysql_thread_id,就是这个事务的线程id,通过kill trx_mysql_thread_id来终止。
当然,死锁的问题不能每次都靠kill线程来解决,这是治标不治本的行为。我们应该尽量在应用端,也就是在编码的过程中避免。有哪些可以避免死锁的方法呢?

1.5、如何防止死锁

  • 在程序中,操作多张表时,尽量以相同的顺序来访问(避免形成等待环路);
  • 尽量避免大事务,占有的资源锁越多,越容易出现死锁。建议拆成小事务。
  • 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。
  • 为表添加合理的索引。防止没有索引出现表锁,出现的死锁的概率会突增。

二、Mysql优化

在这里插入图片描述

三、Sql优化

SQL分析主要有两个切入点:

  1. EXPLAIN 执行计划分析
  2. 数据库慢SQL查询

3.1、EXPLAIN执行计划分析

MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出SELECT 执行计划的详细信息, 这些信息给到开发人员参考并作出优化的方向。
为了更好的展示Explain的效果,首先来初始化一个SQL脚本

-- 创建课程表
DROP TABLE IF EXISTS course;
CREATE TABLE `course` (
`cid` int(3) DEFAULT NULL,
`cname` varchar(20) DEFAULT NULL,
`tid` int(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 创建教师表
DROP TABLE IF EXISTS teacher;
CREATE TABLE `teacher` (
`tid` int(3) DEFAULT NULL,
`tname` varchar(20) DEFAULT NULL,
`tcid` int(3) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 创建教师联系方式表
DROP TABLE IF EXISTS teacher_contact;
CREATE TABLE `teacher_contact` (
`tcid` int(3) DEFAULT NULL,
`phone` varchar(200) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 插入数据
INSERT INTO `course` VALUES ('1', 'mysql', '1');
INSERT INTO `course` VALUES ('2', 'jvm', '1');
INSERT INTO `course` VALUES ('3', 'juc', '2');
INSERT INTO `course` VALUES ('4', 'spring', '3');
INSERT INTO `teacher` VALUES ('1', 'qingshan', '1');
INSERT INTO `teacher` VALUES ('2', 'huihui', '2');
INSERT INTO `teacher` VALUES ('3', 'mic', '3');
INSERT INTO `teacher_contact` VALUES ('1', '13688888888');
INSERT INTO `teacher_contact` VALUES ('2', '18166669999');
INSERT INTO `teacher_contact` VALUES ('3', '17722225555');

接着我们执行下面一个语句

explain select * from course;

在Explain中可以看到很多的数据列,下面分别来说明一下每个数据列的含义。
在这里插入图片描述
官方文档

3.1.1、id

id是查询序列编号,每张表都是单独访问的,一个SELECT就会有一个序号,比如下面这样一个sql。

explain select tc.phone from teacher_contact tc where tcid=
(select tcid from teacher t where t.tid=
(select c.tid from course c where c.cname='mysql'));

对应的执行计划如下:
在这里插入图片描述
查询顺序:course c——teacher t——teacher_contact tc。
先查课程表,再查老师表,最后查老师联系方式表。子查询只能以这种方式进行,只有拿到内层的结果之后才能进行外层的查询。
还有一种查询的情况,id的值相同,查询语句如下:

-- 查询课程ID为2,或者联系表ID为3的老师
EXPLAIN
SELECT t.tname,c.cname,tc.phone
FROM teacher t, course c, teacher_contact tc
WHERE t.tid = c.tid
AND t.tcid = tc.tcid
AND (c.cid = 2
OR tc.tcid = 3);

执行计划如下图所示:
在这里插入图片描述
这种连接查询的情况下,id值相同,表的查询顺序是从上往下执行。
查询的顺序是teacher t(3条)——course c(4条)——teacher_contact tc(3条)。
在连接查询中,先查询的叫做驱动表,后查询的叫做被驱动表。
应该先查小表(得到结果少的表)还是大表(得到结果多的表)?我们肯定要把小表放在前面查询,因为它的中间结果最少。 (小表驱动大表的思想)
因此,总结来看: ID不同的先大后小,ID相同的从上往下。

3.1.2、select_type

select_type表示查询类型,它的常用取值类型如下:

  • SIMPLE, 表示此查询不包含 UNION 查询或子查询
  • PRIMARY, 表示此查询是最外层的查询
  • UNION, 表示此查询是 UNION 的第二或随后的查询
  • DEPENDENT UNION, UNION 中的第二个或后面的查询语句, 取决于外面的查询
  • UNION RESULT, UNION 的结果
  • SUBQUERY, 子查询中的第一个 SELECT
  • DEPENDENT SUBQUERY: 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果.
  • DERIVED: 在from列表中包含的子查询会被标记为DERIVED(衍生),MySQL会递归执行这些子查询,将结果放在临时表中。

下面对常规类型做一个简单的说明:

  • SIMPLE

简单查询,不包含子查询,不包含关联查询union

EXPLAIN SELECT * FROM teacher;

执行计划如下图所示:
在这里插入图片描述

  • PRIMARY/SUBQUERY
    执行下面这种包含多个子查询的语句
select tc.phone from teacher_contact tc where tcid=
(select tcid from teacher t where t.tid=
(select c.tid from course c where c.cname='mysql'));

执行计划如下:
在这里插入图片描述
从上图的执行计划中可以看到,它有两种类型:

  1. primary, 表示SQL语句中的主查询,也就是最外层的查询。
  2. subquery, 子查询中的所有内查询,都是subquery类型。
  • DERIVED
    DERIVED类型,衍生查询,表示的到最终查询结果之前会用到临时表,比如
-- 查询ID为1或2的老师教授的课程
EXPLAIN SELECT cr.cname
FROM (
SELECT * FROM course WHERE tid = 1
UNION
SELECT * FROM course WHERE tid = 2
) cr;

执行计划如下图所示:
在这里插入图片描述
注意看,id=2的查询类型是DERIVED,id=3的查询类型是UNION。执行顺序如下:
1、先执行UNION右边的表,也就是(SELECT * FROM course WHERE tid=2),再执行左边的表SELECT * FROM course WHERE tid = 1,此时左边表的类型是DERIVED。
2. UNION RESULT,显示那些表之间存在UNION查询,<union2,3> 表示id=2和id=3的查询存在union。

3.1.3、type连接类型

type 字段比较重要, 它提供了判断查询是否高效的重要依据,通过type 字段, 我们判断此次查询是全表扫描还是索引扫描等。type常见的取值类型有很多,比如system/const/eq_ref/ref/range/index/all等。下面详细展开说明一下
const
const: 针对主键或唯一索引的等值查询扫描, 最多只返回一行数据. const 查询速度非常快, 因为它仅仅读取一次即可。比如下面这个sql,根据主键id=1查询表的数据。

explain select * from user_innodb where id=1;

执行计划如下:

在这里插入图片描述
system
system: 表中只有一条数据. 这个类型是特殊的 const 类型。
对于MyISAM、Memory的表,只查询到一条记录,也是system。

-- 建表指定MyISAM存储引擎
CREATE TABLE `table1` (
`id` int NOT NULL,
`a` int DEFAULT NULL,
`b` int DEFAULT NULL,
`c` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci;

-- 插入一条数据
insert into table1 value(1,1,1,1);

-- 查看执行计划
explain select * from table1

执行计划如下
在这里插入图片描述
eq_ref
在多表连接查询中,被驱动表通过唯一索引(UNIQUE或PRIMARY KEY)进行访问的时候,被驱动表的访问方式就是eq_ref,通过下面这条sql进行演示

--增加主键索引
ALTER TABLE teacher_contact ADD PRIMARY KEY(tcid);  
explain select t.tcid from teacher t,teacher_contact tc where t.tcid = tc.tcid;

执行计划如下:
在这里插入图片描述
ref
查询用到了非唯一性索引,或者关联操作只使用了索引的最左前缀,则连接类型是ref。
下面通过sql演示一下这种类型:

-- 增加普通索引
ALTER TABLE teacher ADD INDEX idx_tcid (tcid);  
explain SELECT * FROM teacher where tcid = 3;

执行计划如下
在这里插入图片描述
range
索引范围扫描。
如果where后面是 between and 或 < 或 > 或 >= 或 <=或in这些,type类型就为range。
下面通过sql演示一下range范围检索

ALTER TABLE teacher ADD INDEX idx_tid (tid);
-- 执行范围查询(字段上有普通索引)
EXPLAIN SELECT * FROM teacher t WHERE t.tid <3;
EXPLAIN SELECT * FROM teacher t WHERE tid BETWEEN 1 AND 2;
-- IN查询也是range(字段有主键索引)
EXPLAIN SELECT * FROM teacher_contact t WHERE tcid in (1,2,3);

注意:
1、mysql中in中的参数个数不受限制,但是sql本身的长度会受到限制,默认是64M。官网参考
2、in通常是走索引的,当in后面的参数个数较多的情况下,就不会再走索引,直接走全表扫描。

index
Full Index Scan,全索引扫描(Full Index Scan)。index 和ALL最大的区别是,index类型只扫描索引树即可,所以它要比ALL的查询效率要快。比如在teacher表中,tid是主键,当我们只查询主键列tid时。

EXPLAIN SELECT tid FROM teacher;

执行计划如下:
在这里插入图片描述
all
Full Table Scan,如果没有索引或者没有用到索引,type就是ALL。代表全表扫描,比如下面这种情况必然是全表扫描。

EXPLAIN SELECT * FROM teacher;

执行计划如下:
在这里插入图片描述

null
不用访问表或者索引就能得到结果,例如:

EXPLAIN select 1 from dual;

执行计划如下:
在这里插入图片描述

3.1.4、possible_key、key

possible_key表示可能用到的索引,key表示实际用到的索引。如果这一列为空,表示没有用到索引。
possible_key可以有一个或者多个,当然,可能用到索引不代表一定用到索引。
下面演示一下这种索引的使用。

-- 首先需要创建一张表,并且建立一个联合索引
CREATE TABLE `user_info` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`gender` tinyint(1) DEFAULT NULL,
`phone` varchar(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name_key` (`name`,`phone`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3000002 DEFAULT
CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- 执行下面这个sql
explain select phone from user_info where phone='126';

执行计划如下图
在这里插入图片描述
这里用到了覆盖索引,也就是是直接在二级索引树上就获得了数据,所以possible_keys和key对应的是联合索引的名字(name_key)。

3.1.5、key_len

索引的长度(使用的字节数)。跟索引字段的类型、长度有关。比如我们执行下面这个sql

explain select * from user_innodb where name ='小明';

执行计划如下图
在这里插入图片描述
可以看到,key_len是1023。我们来看下这个1023是如何计算的,首先在name和phone上建立了联合索引,而name定义的长度是255、phone的长度是11。这里索引只用到了name字段,所以定义长度是255,而在utf8mb4编码中,一个字符占4个字节,所以255*4=1020。另外,使用可变长字段varchar,需要额外增加2个字节,允许NULL需要额外增加1个字节,所以一共是1023个字节。key_len越长,表示使用的索引范围越广,比如我们再使用下面这个sql执行一次

explain select * from user_innodb where name ='小明' and phone='13002811115';

可以看到,key_len=1070, 因为phone是varchar类型长度为11,字节长度=11*4 =44 再加三个字节一共是47。所以一共是1070个字节。

3.1.6、rows

MySQL认为扫描多少行才能返回请求的数据,是一个预估值,一般来说行数越少越好。

3.1.7、filtered

Filtered表示返回结果的行数占需读取行数的百分比 ,它只对index和all的扫描有效。
如果比例很低,说明存储引擎层返回的数据需要经过大量过滤,这个是会消耗性能的,需要关注。
官网参考

3.1.8、ref

使用哪个列或者常数和索引一起从表中筛选数据。

explain select * from user_info where name ='小明' and phone='13002811115';

执行计划如下图:
在这里插入图片描述
上面的ref,用到了两个常量进行数据的筛选。

3.1.9、Extra

EXplain 中的很多额外的信息会在 Extra 字段显示, 常见的有以下几种内容:

  • Using filesort
    当 Extra 中有 Using filesort 时, 表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果。一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大。
--先删除user_info中的联合索引
alter table user_info drop index name_key;
explain select * from user_innodb order by name;

得到的执行计划如下图
在这里插入图片描述

  • Using index
    “覆盖索引扫描”, 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错。
-- 下面查询的tid直接可以从索引中检索到
EXPLAIN SELECT tid FROM teacher ;

得到的执行计划如下图
在这里插入图片描述

  • Using temporary
    查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 查询效率不高, 建议优化。
    下面这个 sql,就会用到 Using temporary
EXPLAIN select t.tid from teacher t join course c on t.tid = c.tid group by t.tid;

得到的执行计划如下图
在这里插入图片描述

3.2、数据库慢查询日志

在一个数据库中,有很多的应用程序来执行sql,我们一般不会等到sql查询慢了才去处理,而是希望能够有一个慢查询的监控,在应用程序中,有两种方式监控。

  1. Druid包提供了慢查询的监控
  2. Mysql提供了慢查询日志

三、BinLog

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

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

相关文章

Cesium 简介

Cesium 简介 一、Cesium 是什么&#xff1f; Cesium 是一个开源 JavaScript 库&#xff0c;用于 3D , 2D , 2.5D 地图可视化。 Cesium 由 AGI 公司计算机图形开发小组与 2011 年研发的。 Cesium 一词来源于化学元素铯&#xff0c;铯是制造原子钟的关键元素&#xff0c;研发小组…

Vue框架实现对前端数据表的增删改查(第六课)

前端对数据的增删改查你看到过吗?今天带你来实现一下在前端就页面上实现对数据的增伤改查 第一部分功能演示 先看下页面效果 增加一条数据 删除一条数据 修改一条数据 查询指定的一条记录 第二部分 上面的功能该如何实现的呢&#xff01;首先又是页面改如何展示…

吃豆人游戏-第12届蓝桥杯Scratch选拔赛真题精选

[导读]&#xff1a;超平老师计划推出Scratch蓝桥杯真题解析100讲&#xff0c;这是超平老师解读Scratch蓝桥真题系列的第79讲。 蓝桥杯选拔赛每一届都要举行4~5次&#xff0c;和省赛、国赛相比&#xff0c;题目要简单不少&#xff0c;再加上篇幅有限&#xff0c;因此我精挑细选…

基于PHP+MySQL的在线投票系统设计与实现

随着时代的发展,人们需要获取更多的信息和用户的意见,这时候就会产生一个投票。转托管模式都是人工发传单,然后填写来进行。但是随着互联网的发展,这种模式已经逐渐被淘汰,人们越来越希望通过更加方便快捷的方式来进行在线投票。这就是在线投票系统,这是我们设计本系统一个初衷…

传奇GOM/GEE微端配置外网架设教程

传奇GOM/GEE微端配置外网架设教程 我是艾西&#xff0c;经常听到一些小伙伴说微端需要购买&#xff1f;其实大家理解错了&#xff0c;传奇微端自己就可以搭建的是不需要购买的&#xff0c;如果是说单独架设到另外一台服务器上那么这才是需要收费的俗称微端服务器。主要用于跑带…

Nginx+keeplived高可用

目录 一、环境准备 1、准备3台centos服务器 2、安装软件 二、keepalived配置 三、nginx进程监视脚本 一、环境准备 1、准备3台centos服务器 服务器名主机名IPVIPNginx代理服务器proxy1192.168.1.10192.168.1.100Nginx代理服务器proxy2192.168.1.20web网站服务器web1192.…

TikTok 的 TAP好货分销服务商招募啦,最新入驻政策速来了解

众所周知&#xff0c;以抖音快手平台为主的内容电商对于国内来说已经司空见惯&#xff0c;内卷到极致&#xff0c;但是对于国外来说还是一个比较新奇的领域。 而海外版抖音 TikTok就成功实现了内容电商的出海&#xff0c;将电商直播带出国门&#xff0c;面向全世界。为了完善T…

【16-配置中心之Nacos的基本使用Nacos服务之命令空间、Nacos服务之配置组、Nacos服务之配置拆分】

一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了&#xff0c;请点击这里&#xff01;】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…

SpringBoot与mockito那点事

题目起的很像那么回事&#xff0c;但是这篇博客本身写的很简单。 我不想写说一堆概念&#xff0c;然后阐释各种概念是什么意思。我喜欢的是直接从例子出发。 package com.example.demo.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; impo…

操作系统的奋斗(一)

第1章 计算机系统概述1.1操作系统的基本概念1.1.1操作系统的概念1.1.2操作系统的特征&#xff08;1&#xff09;并发&#xff08;2&#xff09;共享&#xff08;3&#xff09;虚拟&#xff08;4&#xff09;异步1.1.3操作系统的目标和功能1.2操作系统发展史&#xff08;1&#…

微信公众号开发:网页授权

一、背景介绍 微信公众号网页授权&#xff0c;目的就是获取用户相关信息&#xff0c;实现自己的业务逻辑&#xff0c;最终于会得到的信息如下表格&#xff0c;本文对应的任务获取到openid即可满足业务需求&#xff0c;本文内容包括环境、操作步骤及相关内容比较详细&#xff0…

3D可视化工厂是如何实现的?

3D可视化工厂是数字孪生的一种方式&#xff0c;是基于智慧工厂现实场景进行虚拟的可视化工厂。 在传统工作模式下&#xff0c;许多工厂仍然存在着数据孤岛、生产过程缺乏监控及工作效率低等问题。如何进行工厂数字化的集中管理&#xff0c;寻求全新的数据驱动型业务解决方案&am…

5.python 列表切片双冒号[: :]和[:,j]

列表切片1.[::]2.[ :,j]3. [::]操作高阶用法1.[::] 适用于Python中的list(也就是数组)&#xff0c;也适用于numpy科学结构(array等)。 使用方法[start: end : step ]&#xff0c;也就是[ 起始下标 : 终止下标 : 间隔距离 ] 切片范围是&#xff1a; start < x < end,注…

iOS 优雅的定义一些全局常量和函数

我们常常使用 #define 来定义一些宏&#xff0c;全局使用。但是可以采用一些更优雅的方式来实现。 方式一&#xff1a;使用 extern 使用场景&#xff1a;工程内多处用到同一个常量。开发中便与管理某一个模块的全局变量&#xff0c;通常创建一个模块的配置文件&#xff0c;里面…

Qt构建时遇到error LNK2019: 无法解析的外部符号 __imp__glAlphaFunc@8,

在我的印象中如果是遇到无法解析的外部命令&#xff0c;无非就是两种情况 头文件定义了方法没有实现lib库没加 因为我这次写的软件我不确定缺失什么库&#xff0c;所以就先检查方法是否未实现&#xff0c;发现方法都实现了&#xff0c;那就只能是lib库缺失的问题了&#xff0…

【机器学习并行计算】1 MapReduce

1 MapReduce 每个节点计算梯度&#xff0c;然后汇聚到一台机子上&#xff0c;再进行梯度下降。时间还需要考虑通信时间。 通信的方式有两种&#xff1a;共享内存和消息传递&#xff1b;在这里存在多机的情况都是消息传递的方式。 通信耗时 MapReduce 会有风险&#xff0c;因为每…

[附源码]java毕业设计农村电商平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Python编程从入门到实践 第九章:类 练习答案记录

Python编程从入门到实践 第九章&#xff1a;类 练习答案记录 练习题导航Python编程从入门到实践 第九章&#xff1a;类 练习答案记录9.1 创建和使用类9.1.1 创建Dog类9.1.2 根据类创建实例练习9-1 餐馆 &#xff1a; 创建一个名为Restaurant 的类&#xff0c; 其方法__init__()…

Android 进程间通信(IPC机制)精炼详解

今天主要对 Android 中的跨进程通信进行总结下&#xff0c;先梳理下里面的涉及的一些概念 进程与线程 进程&#xff1a; 系统中正在运行的一个应用程序&#xff0c;某个程序一旦运行就是一个进程&#xff0c;是资源分配的最小单位&#xff1b;线程&#xff1a; 程序执行的最小…

曙光云使用说明

平台链接 https://ac.sugon.com/ac/home/index.html 控制台界面 创建个人工作目录及上传文件。点击概览页面顶端的 E-Shell 菜单栏&#xff0c;进入所连主机的 Shell 终端。在用户目录下新建个人工作目录&#xff0c;如&#xff1a;mkdir ywj2 安装MiniConda&#xff08;推荐…