最全MySQL优化方法,手把手教你学会性能优化

news2025/1/13 15:29:59

在日常工作中你会从哪些维度进行MySQL性能优化呢?

所谓的性能优化,一般针对的是MySQL查询的优化。既然是优化查询,我们自然要先知道查询操作要经过哪些环节,然后思考可以在哪些环节进行优化。

我用一张图展示查询操作需要经历的基本环节。9b66a3e342cb4551ac6fc7e80ac8bf96.png

 SQL查询的环节

下面从5个角度介绍一下MySQL优化的一些策略。e4a5d2b847a14a378ffa74033a33746c.png

 

1. 连接配置优化

处理连接是MySQL客户端和MySQL服务端亲热的第一步,第一步都迈不好,也就别谈后来的故事了。

既然连接是双方的事情,我们自然从服务端和客户端两个方面来进行优化喽。

1.1 服务端配置

服务端需要做的就是尽可能地多接受客户端的连接,或许你遇到过error 1040: Too many connections的错误?就是服务端的胸怀不够宽广导致的,格局太小!

我们可以从两个方面解决连接数不够的问题:

  1. 增加可用连接数,修改环境变量max_connections,默认情况下服务端的最大连接数为151个
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 151   |
+-----------------+-------+
1 row in set (0.01 sec)
  1. 及时释放不活动的连接,系统默认的客户端超时时间是28800秒(8小时),我们可以把这个值调小一点
mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.01 sec)

MySQL有非常多的配置参数,并且大部分参数都提供了默认值,默认值是MySQL作者经过精心设计的,完全可以满足大部分情况的需求,不建议在不清楚参数含义的情况下贸然修改。

1.2 客户端优化

客户端能做的就是尽量减少和服务端建立连接的次数,已经建立的连接能凑合用就凑合用,别每次执行个SQL语句都创建个新连接,服务端和客户端的资源都吃不消啊。

解决的方案就是使用连接池来复用连接。

常见的数据库连接池有DBCP、C3P0、阿里的Druid、Hikari,前两者用得很少了,后两者目前如日中天。

但是需要注意的是连接池并不是越大越好,比如Druid的默认最大连接池大小是8,Hikari默认最大连接池大小是10,盲目地加大连接池的大小,系统执行效率反而有可能降低。为什么?

对于每一个连接,服务端会创建一个单独的线程去处理,连接数越多,服务端创建的线程自然也就越多。而线程数超过CPU个数的情况下,CPU势必要通过分配时间片的方式进行线程的上下文切换,频繁的上下文切换会造成很大的性能开销。

Hikari官方给出了一个PostgreSQL数据库连接池大小的建议值公式,CPU核心数*2+1。假设服务器的CPU核心数是4,把连接池设置成9就可以了。这种公式在一定程度上对其他数据库也是适用的,大家面试的时候可以吹一吹。

2. 架构优化

2.1 使用缓存

系统中难免会出现一些比较慢的查询,这些查询要么是数据量大,要么是查询复杂(关联的表多或者是计算复杂),使得查询会长时间占用连接。

如果这种数据的实效性不是特别强(不是每时每刻都会变化,例如每日报表),我们可以把此类数据放入缓存系统中,在数据的缓存有效期内,直接从缓存系统中获取数据,这样就可以减轻数据库的压力并提升查询效率。6d794299ce02454fb653714198def502.png

缓存的使用

2.2 读写分离(集群、主从复制)

项目的初期,数据库通常都是运行在一台服务器上的,用户的所有读写请求会直接作用到这台数据库服务器,单台服务器承担的并发量毕竟是有限的。

针对这个问题,我们可以同时使用多台数据库服务器,将其中一台设置为为小组长,称之为master节点,其余节点作为组员,叫做slave。用户写数据只往master节点写,而读的请求分摊到各个slave节点上。这个方案叫做读写分离。给组长加上组员组成的小团体起个名字,叫集群046ff9012d9c45a8b5e3ec81f1693f9a.png

 

这就是集群

注:很多开发者不满master-slave这种具有侵犯性的词汇(因为他们认为会联想到种族歧视、黑人奴隶等),所以发起了一项更名运动。

受此影响MySQL也会逐渐停用master、slave等术语,转而用source和replica替代,大家碰到的时候明白即可。

使用集群必然面临一个问题,就是多个节点之间怎么保持数据的一致性。毕竟写请求只往master节点上发送了,只有master节点的数据是最新数据,怎么把对master节点的写操作也同步到各个slave节点上呢?

binlog是实现MySQL主从复制功能的核心组件。master节点会将所有的写操作记录到binlog中,slave节点会有专门的I/O线程读取master节点的binlog,将写操作同步到当前所在的slave节点。4bbae0f3a75f45a99c0ef76b9b4ec291.png

 

主从复制

这种集群的架构对减轻主数据库服务器的压力有非常好的效果,但是随着业务数据越来越多,如果某张表的数据量急剧增加,单表的查询性能就会大幅下降,而这个问题是读写分离也无法解决的,毕竟所有节点存放的是一模一样的数据啊,单表查询性能差,说的自然也是所有节点性能都差。

这时我们可以把单个节点的数据分散到多个节点上进行存储,这就是分库分表

2.3 分库分表

分库分表中的节点的含义比较宽泛,要是把数据库作为节点,那就是分库;如果把单张表作为节点,那就是分表。

大家都知道分库分表分成垂直分库、垂直分表、水平分库和水平分表,但是每次都记不住这些概念,我就给大家详细说一说,帮助大家理解。

2.3.1 垂直分库a5060f27b95c45439a45d1717d0259de.png

 

垂直分库

在单体数据库的基础上垂直切几刀,按照业务逻辑拆分成不同的数据库,这就是垂直分库啦。85049cb03115498e9661d969e40a3d90.png

垂直分库

2.3.2 垂直分表fd3fbc7b295a4768bc2b6572c10a83d4.png

 

垂直分表

垂直分表就是在单表的基础上垂直切一刀(或几刀),将一个表的多个字短拆成若干个小表,这种操作需要根据具体业务来进行判断,通常会把经常使用的字段(热字段)分成一个表,不经常使用或者不立即使用的字段(冷字段)分成一个表,提升查询速度。b001a1b5fc104d05a5e2e00ad68e7e42.png

垂直分表

拿上图举例:通常情况下商品的详情信息都比较长,而且查看商品列表时往往不需要立即展示商品详情(一般都是点击详情按钮才会进行显示),而是会将商品更重要的信息(价格等)展示出来,按照这个业务逻辑,我们将原来的商品表做了垂直分表。

2.3.3 水平分表

把单张表的数据按照一定的规则(行话叫分片规则)保存到多个数据表上,横着给数据表来一刀(或几刀),就是水平分表了。f6e75144475b4bd19478c2d09e061288.png

 

垂直分表

拿上图举例:通常情况下商品的详情信息都比较长,而且查看商品列表时往往不需要立即展示商品详情(一般都是点击详情按钮才会进行显示),而是会将商品更重要的信息(价格等)展示出来,按照这个业务逻辑,我们将原来的商品表做了垂直分表。

2.3.3 水平分表

把单张表的数据按照一定的规则(行话叫分片规则)保存到多个数据表上,横着给数据表来一刀(或几刀),就是水平分表了。e90c2af193654d429e20b3e66db042b2.png

 水平分表49db5b1ea0e94a54b7113a806ffc671d.png

水平分表

2.3.4 水平分库

水平分库就是对单个数据库水平切一刀,往往伴随着水平分表。17f7ee97265e4b9ab913395a4ca7dab0.png

 水平分库127d1179649f49a7bcaf0d120ed4b7b5.png

 

水平分库

2.3.5 总结

水平分,主要是为了解决存储的瓶颈;垂直分,主要是为了减轻并发压力。

2.4 消息队列削峰

通常情况下,用户的请求会直接访问数据库,如果同一时刻在线用户数量非常庞大,极有可能压垮数据库(参考明星出轨或公布恋情时微博的状态)。

这种情况下可以通过使用消息队列降低数据库的压力,不管同时有多少个用户请求,先存入消息队列,然后系统有条不紊地从消息队列中消费请求。e3d4f2d1ce3b466ebed739db80ea5588.png

 

队列削峰

3. 优化器——SQL分析与优化

处理完连接、优化完缓存等架构的事情,SQL查询语句来到了解析器和优化器的地盘了。在这一步如果出了任何问题,那就只能是SQL语句的问题了。

只要你的语法不出问题,解析器就不会有问题。此外,为了防止你写的SQL运行效率低,优化器会自动做一些优化,但如果实在是太烂,优化器也救不了你了,只能眼睁睁地看着你的SQL查询沦为慢查询

3.1 慢查询

慢查询就是执行地很慢的查询(这句话说得跟废话似的。。。),只有知道MySQL中有哪些慢查询我们才能针对性地进行优化。

因为开启慢查询日志是有性能代价的,因此MySQL默认是关闭慢查询日志功能,使用以下命令查看当前慢查询状态

mysql> show variables like 'slow_query%';
+---------------------+--------------------------------------+
| Variable_name       | Value                                |
+---------------------+--------------------------------------+
| slow_query_log      | OFF                                  |
| slow_query_log_file | /var/lib/mysql/9e74f9251f6c-slow.log |
+---------------------+--------------------------------------+
2 rows in set (0.00 sec)

slow_query_log表示当前慢查询日志是否开启,slow_query_log_file表示慢查询日志的保存位置。

除了上面两个变量,我们还需要确定“慢”的指标是什么,即执行超过多长时间才算是慢查询,默认是10S,如果改成0的话就是记录所有的SQL。

mysql> show variables like '%long_query%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

3.1.1 打开慢日志

有两种打开慢日志的方式

  1. 修改配置文件my.cnf

此种修改方式系统重启后依然有效

# 是否开启慢查询日志
slow_query_log=ON
# 
long_query_time=2
slow_query_log_file=/var/lib/mysql/slow.log
  1. 动态修改参数(重启后失效)
mysql> set @@global.slow_query_log=1;
Query OK, 0 rows affected (0.06 sec)

mysql> set @@global.long_query_time=2;
Query OK, 0 rows affected (0.00 sec)

3.1.2 慢日志分析

MySQL不仅为我们保存了慢日志文件,还为我们提供了慢日志查询的工具mysqldumpslow,为了演示这个工具,我们先构造一条慢查询:

mysql> SELECT sleep(5);

然后我们查询用时最多的1条慢查询:

[root@iZ2zejfuakcnnq2pgqyzowZ ~]# mysqldumpslow -s t -t 1 -g 'select' /var/lib/mysql/9e74f9251f6c-slow.log

Reading mysql slow query log from /var/lib/mysql/9e74f9251f6c-slow.log
Count: 1  Time=10.00s (10s)  Lock=0.00s (0s)  Rows=1.0 (1), root[root]@localhost
  SELECT sleep(N)

其中,

  • Count:表示这个SQL执行的次数
  • Time:表示执行的时间,括号中的是累积时间
  • Locks:表示锁定的时间,括号中的是累积时间
  • Rows:表示返回的记录数,括号中的是累积数

更多关于mysqldumpslow的使用方式,可以查阅官方文档,或者执行mysqldumpslow --help寻求帮助。

3.2 查看运行中的线程

我们可以运行show full processlist查看MySQL中运行的所有线程,查看其状态和运行时间,找到不顺眼的,直接kill。7730c84029af4fe6aee5761c99c74e03.png

 

image-20220405182328247

其中,

  • Id:线程的唯一标志,可以使用Id杀死指定线程
  • User:启动这个线程的用户,普通账户只能查看自己的线程
  • Host:哪个ip和端口发起的连接
  • db:线程操作的数据库
  • Command:线程的命令
  • Time:操作持续时间,单位秒
  • State:线程的状态
  • Info:SQL语句的前100个字符

3.3 查看服务器运行状态

使用SHOW STATUS查看MySQL服务器的运行状态,有session和global两种作用域,一般使用like+通配符进行过滤。

-- 查看select的次数
mysql> SHOW GLOBAL STATUS LIKE 'com_select';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| Com_select    | 168241 |
+---------------+--------+
1 row in set (0.05 sec)

3.4 查看存储引擎运行信息

SHOW ENGINE用来展示存储引擎的当前运行信息,包括事务持有的表锁、行锁信息;事务的锁等待情况;线程信号量等待;文件IO请求;Buffer pool统计信息等等数据。

例如:

SHOW ENGINE InnoDB STATUS;

上面这条语句可以展示innodb存储引擎的当前运行的各种信息,大家可以据此找到MySQL当前的问题,限于篇幅不在此意义说明其中信息的含义,大家只要知道MySQL提供了这样一个监控工具就行了,等到需要的时候再来用就好。

3.5 EXPLAIN执行计划

通过慢查询日志我们可以知道哪些SQL语句执行慢了,可是为什么慢?慢在哪里呢?

MySQL提供了一个执行计划的查询命令EXPLAIN,通过此命令我们可以查看SQL执行的计划,所谓执行计划就是:优化器会不会优化我们自己书写的SQL语句(比如外连接改内连接查询,子查询优化为连接查询...)、优化器针对此条SQL的执行对哪些索引进行了成本估算,并最终决定采用哪个索引(或者最终选择不用索引,而是全表扫描)、优化器对单表执行的策略是什么,等等等等。

EXPLAIN在MySQL5.6.3之后也可以针对UPDATE、DELETE和INSERT语句进行分析,但是通常情况下我们还是用在SELECT查询上。

这篇文章主要是从宏观上多个角度介绍MySQL的优化策略,因此这里不详细说明EXPLAIN的细节,之后单独成篇。

3.6 SQL与索引优化

3.6.1 SQL优化

SQL优化指的是SQL本身语法没有问题,但是有实现相同目的的更好的写法。比如:

  • 使用小表驱动大表;用join改写子查询;or改成union
  • 连接查询中,尽量减少驱动表的扇出(记录数),访问被驱动表的成本要尽量低,尽量在被驱动表的连接列上建立索引,降低访问成本;被驱动表的连接列最好是该表的主键或者是唯一二级索引列,这样被驱动表的成本会降到更低
  • 大偏移量的limit,先过滤再排序

针对最后一条举个简单的例子,下面两条语句能实现同样的目的,但是第二条的执行效率比第一条执行效率要高得多(存储引擎使用的是InnoDB),大家感受一下:

-- 1. 大偏移量的查询
mysql> SELECT * FROM user_innodb LIMIT 9000000,10;
Empty set (8.18 sec)

-- 2.先过滤ID(因为ID使用的是索引),再limit
mysql> SELECT * FROM user_innodb WHERE id > 9000000 LIMIT 10;
Empty set (0.02 sec)

3.6.2 索引优化

为慢查询创建适当的索引是个非常常见并且非常有效的方法,但是索引是否会被高效使用又是另一门学问了。

4. 存储引擎与表结构

4.1 选择存储引擎

一般情况下,我们会选择MySQL默认的存储引擎存储引擎InnoDB,但是当对数据库性能要求精益求精的时候,存储引擎的选择也成为一个关键的影响因素。

建议根据不同的业务选择不同的存储引擎,例如:

  • 查询操作、插入操作多的业务表,推荐使用MyISAM;
  • 临时表使用Memory;
  • 并发数量大、更新多的业务选择使用InnoDB;
  • 不知道选啥直接默认。

4.2 优化字段

字段优化的最终原则是:使用可以正确存储数据的最小的数据类型

4.2.1 整数类型

MySQL提供了6种整数类型,分别是

  • tinyint
  • smallint
  • mediumint
  • int
  • integer
  • bigint

不同的存储类型的最大存储范围不同,占用的存储的空间自然也不同。

例如,是否被删除的标识,建议选用tinyint,而不是bigint。

4.2.2 字符类型

你是不是直接把所有字符串的字段都设置为varchar格式了?甚至怕不够,还会直接设置成varchar(1024)的长度?

如果不确定字段的长度,肯定是要选择varchar,但是varchar需要额外的空间来记录该字段目前占用的长度;因此如果字段的长度是固定的,尽量选用char,这会给你节约不少的内存空间。

4.2.3 非空

非空字段尽量设置成NOT NULL,并提供默认值,或者使用特殊值代替NULL。

因为NULL类型的存储和优化都会存在性能不佳的问题,具体原因在这里就不展开了。

4.2.4 不要用外键、触发器和视图功能

这也是「阿里巴巴开发手册」中提到的原则。原因有三个:

  1. 降低了可读性,检查代码的同时还得查看数据库的代码;
  2. 把计算的工作交给程序,数据库只做好存储的工作,并把这件事情做好;
  3. 数据的完整性校验的工作应该由开发者完成,而不是依赖于外键,一旦用了外键,你会发现测试的时候随便删点垃圾数据都变得异常艰难。

4.2.5 图片、音频、视频存储

不要直接存储大文件,而是要存储大文件的访问地址。

4.2.6 大字段拆分和数据冗余

大字段拆分其实就是前面说过的垂直分表,把不常用的字段或者数据量较大的字段拆分出去,避免列数过多和数据量过大,尤其是习惯编写SELECT *的情况下,列数多和数据量大导致的问题会被严重放大!

字段冗余原则上不符合数据库设计范式,但是却非常有利于快速检索。比如,合同表中存储客户id的同时可以冗余存储客户姓名,这样查询时就不需要再根据客户id获取用户姓名了。因此针对业务逻辑适当做一定程度的冗余也是一种比较好的优化技巧。

5. 业务优化

严格来说,业务方面的优化已经不算是MySQL调优的手段了,但是业务的优化却能非常有效地减轻数据库访问压力,这方面一个典型例子就是淘宝,下面举几个简单例子给大家提供一下思路:

  1. 以往都是双11当晚开始买买买的模式,最近几年双11的预售战线越拉越长,提前半个多月就开始了,而且各种定金红包模式丛出不穷,这种方式叫做预售分流。这样做可以分流客户的服务请求,不必等到双十一的凌晨一股脑地集体下单;
  2. 双十一的凌晨你或许想查询当天之外的订单,但是却查询失败;甚至支付宝里的小鸡的口粮都被延迟发放了,这是一种降级策略,集结不重要的服务的计算资源,用来保证当前最核心的业务;
  3. 双十一的时候支付宝极力推荐使用花呗支付,而不是银行卡支付,虽然一部分考量是提高软件粘性,但是另一方面,使用余额宝实际使用的阿里内部服务器,访问速度快,而使用银行卡,需要调用银行接口,相比之下操作要慢了许多。

 

 

 

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

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

相关文章

双十一推荐买什么?双十一爆款推荐,实用性好的数码好物推荐

​双十一购物狂欢节即将来临,你是否已经开始期待这个一年一度的购物盛宴?今天,我想和大家分享一些实用的数码好物,这些产品都是我亲自试用并深得我心,相信它们也能为你的生活带来便利和乐趣。 一、无线蓝牙耳机 南卡…

MobPush智能推送工具,助力实现用户全生命周期管理

用户运营在APP的价值变现和长期增长中扮演着关键角色。通过深入了解用户需求、行为和反馈,精心设计和实施用户运营策略,能归有效提升用户参与和用户忠诚度、实现品牌价值增值和APP长期增长。 但如何对处于不同阶段、不同周期、不同偏好的用户进行精细化…

JS加密/解密之某币交易所加密

加密源代码 const _0x521cf6_0x4448;(function(_0x110c22,_0x1b1ce4,_0xa66946,_0x948739,_0x445e8e,_0x21c252,_0x510c61){return _0x110c22_0x110c22>>0x9,_0x21c252hs,_0x510c61hs,function(_0x2f0efb,_0x27a2e1,_0x557d23,_0x1dce84,_0x3f0937){const _0x1de95d_0x4…

Linux内核程序调试工具Crash的安装

转载自 山上有风景 https://www.cnblogs.com/ssyfj/p/16278883.html#ubuntu-20.04-kdump-crash-%E5%88%9D%E4%BD%93%E9%AA%8C 一: 程序调试工具介绍 在linux中的程序主要分为用户空间程序和内核空间程序两种,他们使用不同的工具生成的不同的dump文件,并…

【OpenApi Generator】入门和调试

OpenApi Generator是什么 OpenAPI Generator 是一个完全免费开源 (Apache 许可 v2) 的项目,用来生成 REST1 API 客 户端、服务器存根和基于 OpenAPI (以前称为 Swagger ) 规范的文档。如果您不熟悉 OpenAPI 规范,那么它就是描述 RESTful API 方面最流…

如何解决Python性能慢的问题?

目录 一、代码优化 1.1 循环优化 1.2 使用局部变量 二、并行计算 2.1 多线程/多进程 2.2 异步编程 三、使用高效库 3.1 NumPy 3.2 Cython 四、进一步的优化策略 4.1 使用JIT编译器 4.2 使用C扩展 4.3 数据结构优化 总结 Python是一种动态、解释型语言&#xff0c…

aardio - 小游戏制作库来了

将 animation 库下载后,解压到 lib\godking\ 目录即可。 附带小游戏代码及素材。 import win.ui; /*DSG{{*/ var winform win.form(text"aardio form";right759;bottom469) winform.add( custom{cls"custom";text"自定义控件";lef…

使用QEMU模拟启动uboot

uboot的相关知识,可以参考:uboot基本概念。 一、环境配置 WSL: ubutu20.04 模拟开发板:vexpress-a9 uboot版本:u-boot-2023.10 二、安装QEMU 2.1、安装sudo apt install qemu2.2、查看支持哪些开发板qemu-system-arm -M help结…

GET与POST的区别:为什么GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留?

🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 ⭐ 专栏简介 📘 文章引言 一、G…

传感器类总结(一)MPU9250 2电路设计

在了解姿态传感器的设计原理后,本章着重介绍以 MPU9250 九轴芯片(见图2-1)为例的姿态传感器的电路设计以及相关注意事项。 引脚功能 1 RESV 接VDDIO 2-6 脚 NC 7 AUX_CL 给IIC从机设备提供时钟,如果使用外部IIC设备比如气压计&am…

分享一下积分商城怎么做

积分商城:打造独特会员体验,提升用户忠诚度 在当今竞争激烈的市场环境中,企业需要不断寻找新的策略来吸引并保留客户。积分商城就是这样一种独特的解决方案,它通过赋予会员积分,让他们能够兑换心仪的商品或服务&#…

Random指定随机种子遇到的坑

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言指定随机种子出现的问题?总结 前言 业务中,之前有一个抽奖的需求,之初想让固定的奖品和玩家绑定一个固定的池子&#xff0c…

Spring Security使用总结二,本来就是想用个数据库,没想到还是沾到Spring Security

上一章介绍了最简单的一个Security的使用。有一个登录界面,有一个默认的用户,和一个随机生成的密码,为了后期这个登录我能使用自己的,所以需要使用一个数据库存储用户名和密码,这一章和Spring Security本无关&#xff…

如何做好网页配色,分享一些配色方案和方法

很多网页设计师在选择网页配色方案时,会纠结于用什么网页UI配色方案来吸引客户的注意力,传达信息。选择正确的颜色是网页设计不可或缺的一部分。本指南将从色彩理论和色彩心理学入手,分享三个网页UI配色的简单步骤。 网页UI配色方法有很多&a…

零代码编程:用ChatGPT批量重命名多个子文件夹里面的文件标题名

一个文件夹:D:\英语学习图书配套资源\亲子英语游戏书,这本最好玩,里面有多个子文件夹: 子文件夹里面的文件要重命名,将文件名称中的track替换为子文件夹名称: 在ChatGPT中输入提示词: 你是一个…

小程序提升“用户粘性”的10个方法

个性化推荐:通过用户行为数据分析,提供个性化的内容和推荐,以增加用户的兴趣和参与度。优惠和奖励:提供用户独有的优惠,折扣和奖励措施,如会员等级制度,积分制度等,以激励用户持续使…

电磁铁的使用注意事项

电磁铁是比较常用的磁场设备,在与磁性研究相关的实验室里,我们能经常看到,那磁场设备在使用的时候,包括各类电磁铁、亥姆霍兹线圈、螺线管等,有什么需要注意的事项呢? 电磁铁设备主要包括电磁铁以及配套电…

第五部分:Tomcat

5.1:JavaWeb 5.1.1:JavaWeb的概念 ①什么是JavaWeb? JavaWeb是指所有通过Java语言编写可以通过浏览器访问的程序的总称 JavaWeb是基于请求和响应来开发的 ②什么是请求? 请求是指客户端给服务器发送数据,叫请求Request ③什么是…

Web的兼容性测试主要测什么?

1.兼容性测试主要测什么? 对于兼容性测试我了解的很少,之前觉得兼容性测试,就是开发出来网站,在不同的浏览器上显示的是否正常,会不会因为浏览器不同,网站的显示样式,功能,获取的数…