MySQL(十三)MySQL性能分析工具:慢查询日志与PROFILE查询成本
性能分析工具SLOW QUERY LOG、PROFILE的使用
数据库调优的目标就是响应速度更快,吞吐量更大。利用宏观的监控工具和微观的日志分析可以帮助我们找到调优的思路和方式。
数据库调优的步骤
整个流程分为了观察(Show Status)和行动(Action)两个部分,S观察会使用相应的分析工具,字母A代表的部分是行动,对应分析可以采取的行动。



- 首先观察服务器状态是否存在
周期性波动,即是否由一些周期性节点造成的(如双十一、促销活动),然后通过增加缓存或者更改缓存失效策略解决 - 如果仍有不规则延迟或者卡顿,就设置慢查询阈值
long_query_time并开启慢查询,记录慢查询到码查询日志中,然后在日志中找到慢查询的sql语句,使用慢查询监控工具如EXPLAIN查看慢查询的执行计划进行分析、或者Show Profiling查看每个步骤的执行时间成本,来判断是由于SQL执行时间较长还是SQL的等待时间比较长导致的延迟卡顿。 - 如果是等待时间比较长,则调优服务器参数(如增加数据库缓存)
- 如果是执行时间较长,应:
- 索引设计优化
- JOIN表过多,进行优化
- 数据库表设计优化
- 如果仍然有问题,则判断是否SQL查询达到了瓶颈,这时候:
- 增加服务器进行主从复制实现读写分离
- 分库分表(垂直分表、垂直分库、水平分表)
小结:

- 在数据库优化中,针对SQL及索引的优化是成本最低的,反而效果也是最好的
- 相反硬件的优化成本最高而效果最差
查看系统性能参数、执行频率
查询语句语法如下:
SHOW [GLOBAL | SESSION] STATUS LIKE '参数';
Connections:连接MySQL服务器的次数
Uptime:MySQL服务器上线运行的时间
slow_queries:慢查询的个数
innodb_rows_%:增删改的行的个数
mysql> show status like 'innodb_rows_%';
+----------------------+---------+
| Variable_name | Value |
+----------------------+---------+
| Innodb_rows_deleted | 0 |
| Innodb_rows_inserted | 1395950 |
| Innodb_rows_read | 8045388 |
| Innodb_rows_updated | 0 |
+----------------------+---------+
4 rows in set (0.00 sec)com_%:增删改查的次数
统计SQL查询成本:last_query_cost
一条查询SQL在执行前需要确定执行计划,如果存在多条执行计划,MySQL会从多条执行计划中选出一条执行成本最小的最为最终的执行计划。
可以通过last_query_cost来查看刚刚执行的最后一条SQL的查询成本,这个变量也是查询效率的一个指标,它的值的含义是该SQL语句查询需要读取的页的数量。
举个栗子,以student_info为例:
mysql> select * from student_info where id = 1065943;
+---------+------------+--------+-----------+----------+---------------------+
| id | student_id | name | course_id | class_id | create_time |
+---------+------------+--------+-----------+----------+---------------------+
| 1065943 | 23672 | VnzJZS | 10089 | 10111 | 2023-04-06 00:16:23 |
+---------+------------+--------+-----------+----------+---------------------+
1 row in set (0.00 sec)
mysql> show status like 'last_query_cost';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| Last_query_cost | 1.000000 |
+-----------------+----------+
1 row in set (0.00 sec)
可以看到该条查询sql需要进行读取一个页的查询成本消耗。
mysql> select * from student_info where id between 1055968 and 1065943;
...
9976 rows in set (0.00 sec)
mysql> show status like 'last_query_cost';
+-----------------+-------------+
| Variable_name | Value |
+-----------------+-------------+
| Last_query_cost | 3912.489842 |
+-----------------+-------------+
1 row in set (0.00 sec)
mysql> select * from student_info where id > 1055968
...
944032 rows in set (0.49 sec)
mysql> show status like 'last_query_cost';
+-----------------+--------------+
| Variable_name | Value |
+-----------------+--------------+
| Last_query_cost | 99910.581873 |
+-----------------+--------------+
1 row in set (0.00 sec)
可以看到两个查询在数据页上有25倍多的差距,但是在查询时间上并没有太大的差别(0.49 0.00),这是因为是采取的顺序读取的方式将数据页一次性加载到了缓冲池中,然后进行查找,虽然页数量增加了很多,但是由于缓冲池的机制,并没有增加很多的查询时间。
SQL查询是一个动态的过程,从页的加载的角度看,有以下两点结论:
- 位置决定效率,如果页本身在缓冲池中,那么效率是最高的,否则还需要从内存或者磁盘中进行读取,其次内存中的页的读取要高于磁盘中的
- 批量决定效率,如果从磁盘中对单一页进行随机读取,那么效率是很差的(大约10ms),但如果是批量对数据页进行读取,则平均每个页面的读取时间就会很小,甚至低于在内存中对单一页的读取。
因此,我们首先要考虑数据存放的位置,如果是经常使用的数据就要放到缓冲池中,其次应尽量一次性批量读取数据,这样单个页的读取效率页得到了提升。
一 定位执行慢的SQL:慢查询日志
MySQL的慢查询日志记录的是超过慢查询时间阈值long_query_time的sql语句,long_query_time的默认时长为10s,因此超过10s的sql就会被认为是慢查询记录到慢查询日志中。
默认情况下mysql数据库没有开启慢查询,需要手动进行开启,但是如果不是调优使用一般不建议开启该参数,因为开启慢查询日志会带来一些性能影响。慢查询日志会将日志记录写到文件中。
开启慢查询日志参数
1 slow_query_log 开启慢查询
mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | OFF |
+----------------+-------+
1 row in set (0.01 sec)
mysql> set slow_query_log = on
-> ;
ERROR 1229 (HY000): Variable 'slow_query_log' is a GLOBAL variable and should be set with SET GLOBAL
mysql> set global slow_query_log = on;
Query OK, 0 rows affected (0.01 sec)
slow_query_log是全局变量,因此设置的时候需要添加global
2 slow_query_log_file 慢查询日志文件位置
mysql> show variables like '%slow_query_log%';
+---------------------+-----------------------------------+
| Variable_name | Value |
+---------------------+-----------------------------------+
| slow_query_log | ON |
| slow_query_log_file | /var/lib/mysql/hadoop102-slow.log |
+---------------------+-----------------------------------+
2 rows in set (0.00 sec)
3 long_query_time 慢查询阈值
mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
mysql> set global long_query_time=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
mysql> set long_query_time=1;
Query OK, 0 rows affected (0.01 sec)
由于long_query_time即是global也是session变量,因此只设置global的话只会对新会话生效,而当前会话还是10s,因此还需要设置一下会话变量
补充:
上面的配置在mysql服务器重启后就会失效,想要进行永久性的设置,需要在mysql配置文件my.cnf中设置参数slow_query_log、slow_query_log_file、long_query_time。

如不指定目录,则会将慢查询日志存储到数据库数据目录下,不指定文件名则默认使用hostname-slow.log
4 slow_queries查看慢查询数目
Show global status like 'slow_queries';
举个栗子,首先创建一个表:
CREATE TABLE student (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`stuno` INT NOT NULL,
`name` VARCHAR(20) DEFAULT NULL,
`age` INT(3) DEFAULT NULL,
`classid` INT(11) DEFAULT NULL,
PRIMARY KEY(`id`)
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET=utf8
创建随机生成数字和字符串的函数,和上一章相同
创建存储过程
DELIMITER //
CREATE PROCEDURE insert_stu1(START INT, max_num INT)
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO student(stuno, NAME, age, classId) VALUES(START + i, rand_string(6), rand_num(10, 100), rand_num(10, 1000));
UNTIL i = max_num
END REPEAT;
COMMIT;
END //
DELIMITER;
执行存储过程
CALL insert_stu1(100001, 4000000);
这时候执行两条sql语句:
mysql> select * from student where name = 'Jhon';
Empty set (1.32 sec)
mysql> select * from student where stuno = 34521;
Empty set (1.47 sec)
与此同时监视的slow_log_file 输出了:
[root@hadoop102 mysql]# tail -f hadoop102-slow.log
/usr/sbin/mysqld, Version: 8.0.31 (MySQL Community Server - GPL). started with:
Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 2023-04-07T08:17:42.255709Z
# User@Host: root[root] @ [192.168.60.1] Id: 128
# Query_time: 1743.052707 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
use atguigudb1;
SET timestamp=1680855460;
CALL insert_stu1(100001, 4000000);
# Time: 2023-04-07T08:21:18.455242Z
# User@Host: root[root] @ localhost [] Id: 123
# Query_time: 1.328363 Lock_time: 0.000006 Rows_sent: 0 Rows_examined: 4000000
SET timestamp=1680855677;
select * from student where name = 'Jhon';
# Time: 2023-04-07T08:21:45.554053Z
# User@Host: root[root] @ localhost [] Id: 123
# Query_time: 1.466888 Lock_time: 0.000002 Rows_sent: 0 Rows_examined: 4000000
SET timestamp=1680855704;
select * from student where stuno = 34521;
slow_queries显示数量为2
mysql> show status like 'slow_queries';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries | 2 |
+---------------+-------+
1 row in set (0.03 sec)
mysqldumpslow慢查询工具
[root@hadoop102 ~]# mysqldumpslow -help
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
Parse and summarize the MySQL slow query log. Options are
--verbose verbose
--debug debug
--help write this text to standard output
-v verbose
-d debug
-s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default
al: average lock time
ar: average rows sent
at: average query time
c: count
l: lock time
r: rows sent
t: query time
-r reverse the sort order (largest last instead of first)
-t NUM just show the top n queries
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time
参数说明
- -a:不使用n、s等字母缩写sql语句中的变量
- -s:排序
- -t:只显示最前面的
[root@hadoop102 ~]# mysqldumpslow -a -s t -t 5 /var/lib/mysql/hadoop102-slow.log
Reading mysql slow query log from /var/lib/mysql/hadoop102-slow.log
Count: 1 Time=1743.05s (1743s) Lock=0.00s (0s) Rows=0.0 (0), root[root]@[192.168.60.1]
CALL insert_stu1(100001, 4000000)
Count: 1 Time=1.47s (1s) Lock=0.00s (0s) Rows=0.0 (0), root[root]@localhost
select * from student where stuno = 34521
Count: 1 Time=1.33s (1s) Lock=0.00s (0s) Rows=0.0 (0), root[root]@localhost
select * from student where name = 'Jhon'
Died at /usr/bin/mysqldumpslow line 162, <> chunk 3.
关闭慢查询日志
永久关闭
修改my.cnf文件,设置slow_query_log为off或者注释掉
[mysqld]
slow_query_log = off
再次重启服务即可
mysql> show variables like '%slow%';
+-----------------------------+-----------------------------------+
| Variable_name | Value |
+-----------------------------+-----------------------------------+
| log_slow_admin_statements | OFF |
| log_slow_extra | OFF |
| log_slow_replica_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/hadoop102-slow.log |
+-----------------------------+-----------------------------------+
7 rows in set (0.03 sec)
mysql> show variables like 'long_query_time';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
1 row in set (0.00 sec)
临时性方式
① 停止慢查询日志功能
SET GLOBAL slow_query_log = off;
② 重启mysql服务
mysql> show variables like '%slow%';
+-----------------------------+-----------------------------------+
| Variable_name | Value |
+-----------------------------+-----------------------------------+
| log_slow_admin_statements | OFF |
| log_slow_extra | OFF |
| log_slow_replica_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/hadoop102-slow.log |
+-----------------------------+-----------------------------------+
7 rows in set (0.03 sec)
mysql> show variables like 'long_query_time';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
1 row in set (0.00 sec)
删除慢查询日志
rm手动删除mysql数据目录下的慢查询日志即可。
[root@hadoop102 mysql]# rm hadoop102-slow.log
rm:是否删除普通文件 "hadoop102-slow.log"?y
重置慢查询日志
可以通过mysqladmin -uroot -p flush-logs命令重置慢查询日志
[root@hadoop102 mysql]# mysqladmin -uroot -p flush-logs slow
Enter password:
慢查询日志都是通过这个命令来删除重建的,一旦执行这个命令,慢查询日志都只保存在新的日志文件中,如果需要旧的就必须实现备份
二 查看SQL的执行成本:SHOW PROFILE
show profile 可以分析当前会话中SQL做了什么、执行的资源消耗情况的工具,可用于sql调优的测量。默认情况下处于关闭状态,并保存最近15次的运行结果。
mysql> show variables like 'profiling';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| profiling | OFF |
+---------------+-------+
1 row in set (0.00 sec)
mysql> set profiling = on;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show variables like 'profiling';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| profiling | ON |
+---------------+-------+
1 row in set (0.00 sec)
show profiles查看最近的sql执行成本
mysql> select * from student where stuno = 34521;
Empty set (1.52 sec)
mysql> select * from student where name = 'Jhon';
Empty set (1.08 sec)
mysql> show profiles;
+----------+------------+-------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-------------------------------------------+
| 1 | 0.00140400 | show variables like 'profiling' |
| 2 | 1.52199250 | select * from student where stuno = 34521 |
| 3 | 1.08189700 | select * from student where name = 'Jhon' |
+----------+------------+-------------------------------------------+
3 rows in set, 1 warning (0.00 sec)
会保存15次查询,Duration为时间
show_profile for显示详细信息
show_profile会显示最近的一次详细信息:
mysql> show profile;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000148 |
| Executing hook on transaction | 0.000028 |
| starting | 0.000010 |
| checking permissions | 0.000006 |
| Opening tables | 0.000056 |
| init | 0.000007 |
| System lock | 0.000008 |
| optimizing | 0.000009 |
| statistics | 0.000047 |
| preparing | 0.000042 |
| executing | 1.081442 |
| end | 0.000019 |
| query end | 0.000005 |
| waiting for handler commit | 0.000011 |
| closing tables | 0.000011 |
| freeing items | 0.000036 |
| cleaning up | 0.000014 |
+--------------------------------+----------+
17 rows in set, 1 warning (0.00 sec)
mysql> show profile for query 2;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000186 |
| Executing hook on transaction | 0.000024 |
| starting | 0.000026 |
| checking permissions | 0.000008 |
| Opening tables | 0.000128 |
| init | 0.000023 |
| System lock | 0.000010 |
| optimizing | 0.000065 |
| statistics | 0.000064 |
| preparing | 0.000022 |
| executing | 1.521179 |
| end | 0.000025 |
| query end | 0.000005 |
| waiting for handler commit | 0.000046 |
| closing tables | 0.000049 |
| freeing items | 0.000044 |
| cleaning up | 0.000090 |
+--------------------------------+----------+
17 rows in set, 1 warning (0.00 sec)
并且也可以查看cpu和堵塞io情况
mysql> show profile cpu, block io for query 2;
+--------------------------------+----------+----------+------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+--------------------------------+----------+----------+------------+--------------+---------------+
| starting | 0.000186 | 0.000072 | 0.000111 | 0 | 0 |
| Executing hook on transaction | 0.000024 | 0.000008 | 0.000013 | 0 | 0 |
| starting | 0.000026 | 0.000011 | 0.000016 | 0 | 0 |
| checking permissions | 0.000008 | 0.000002 | 0.000004 | 0 | 0 |
| Opening tables | 0.000128 | 0.000051 | 0.000078 | 0 | 0 |
| init | 0.000023 | 0.000009 | 0.000014 | 0 | 0 |
| System lock | 0.000010 | 0.000003 | 0.000005 | 0 | 0 |
| optimizing | 0.000065 | 0.000026 | 0.000041 | 0 | 0 |
| statistics | 0.000064 | 0.000025 | 0.000039 | 0 | 0 |
| preparing | 0.000022 | 0.000009 | 0.000012 | 0 | 0 |
| executing | 1.521179 | 1.407445 | 0.269692 | 4096 | 0 |
| end | 0.000025 | 0.000015 | 0.000000 | 0 | 0 |
| query end | 0.000005 | 0.000005 | 0.000000 | 0 | 0 |
| waiting for handler commit | 0.000046 | 0.000048 | 0.000000 | 0 | 0 |
| closing tables | 0.000049 | 0.000048 | 0.000000 | 0 | 0 |
| freeing items | 0.000044 | 0.000044 | 0.000000 | 0 | 0 |
| cleaning up | 0.000090 | 0.000091 | 0.000000 | 0 | 0 |
+--------------------------------+----------+----------+------------+--------------+---------------+
17 rows in set, 1 warning (0.00 sec)
可以看出上面两条sql的主要执行时间都在executing执行上,只需要添加索引即可大幅度缩减执行时间

MySQL(十三)MySQL性能分析工具:慢查询日志与PROFILE查询成本的更多相关文章
- MySQL监控、性能分析——工具篇
https://blog.csdn.net/leamonjxl/article/details/6431444 MySQL越来越被更多企业接受,随着企业发展,MySQL存储数据日益膨胀,MySQL的性 ...
- MySQL监控、性能分析——工具篇(转载)
MySQL越来越被更多企业接受,随着企业发展,MySQL存储数据日益膨胀,MySQL的性能分析.监控预警.容量扩展议题越来越多.“工欲善其事,必先利其器”,那么我们如何在进行MySQL性能分析.监控预 ...
- 11个Visual Studio代码性能分析工具
软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...
- .NET 11 个 Visual Studio 代码性能分析工具
原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...
- 11 个 Visual Studio 代码性能分析工具
软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...
- 8、msyql性能分析工具
性能分析工具 1服务器优化的步骤 2查询系统参数 在MySQL中,可以使用 SHOW STATUS 语句查询一些MySQL数据库服务器的性能参数.执行频率 . SHOW STATUS语句语法如下: S ...
- mysql基础之日志管理(查询日志、慢查询日志、错误日志、二进制日志、中继日志、事务日志)
日志文件记录了MySQL数据库的各种类型的活动,MySQL数据库中常见的日志文件有 查询日志,慢查询日志,错误日志,二进制日志,中继日志 ,事务日志. 修改配置或者想要使配置永久生效需将内容写入配置文 ...
- Java 性能分析工具 , 第 1 部分: 操作系统工具
引言 性能分析的前提是将应用程序内部的运行状况以及应用运行环境的状况以一种可视化的方式更加直接的展现出来,如何来达到这种可视化的展示呢?我们需要配合使用操作系统中集成的程序监控工具和 Java 中内置 ...
- php性能分析工具 - xhprof的安装使用
一.前言 有用的东西还是记录下来吧,也方便以后的查询:这次记录一下xhprof的安装使用: xhprof是facebook开源出来的一个php轻量级的性能分析工具,跟Xdebug类似,但性能开销更低, ...
- MySQL一般查询日志或者慢查询日志历史数据的清理
general log&slow query log 对于MySQL的一般查询日志和慢查询日志,开启比较简单,其中公用的一个参数是log_output,log_output控制着慢查询和一般查 ...
随机推荐
- Day3 准备步入入门.ok
安装开发环境(6.21周一) 卸载JDK 删除Java的安装目录 打开我的电脑-->属性-->高级系统设置-->环境变量 删除JAVA_HOME 删除path下添加的JAVA目录 安 ...
- 【原创】android 7.0 通知报错 java.lang.SecurityException: You need MANAGE_USERS permission to: check if specified user a managed profile outside your profile group
项目中在后台发送通知,突然某一天测出在Android 7.0上通知发送失败,那么根据提示,我们尝试加了MANAGE_USERS权限,看起来是个系统级别权限,验证后果然无效.接着在搜索后都无果,似乎大家 ...
- java map重写 转大写、转驼峰
/** * @author admin * @Description * 转大写 */ public class HashMapUpper<V> extends HashMap<St ...
- FLINK集群搭建
常用命令总结 启动/停止 flink 集群 ./bin/start-cluster.sh./bin/stop-cluster.sh 启动或停止JOBMANAGER bin/jobmanager.sh ...
- Java开发词汇
Java基础常见英语词汇(70个) OO: object-oriented ,面向对象 OOP: object-oriented programming,面向对象编程 JDK:Java develop ...
- 2021.06.29 mac系统下zsh: command not found:***报错问题
最近老是遇到zsh: command not found:vue,zsh: command not found:nrm, zsh: command not found:tsc, zsh: comman ...
- java的死锁与解决方法
一.什么是死锁? 死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无限等待. 二.产生死锁的原因与四个条件 2.1 死锁原因 竞争资 ...
- GRAPH ATTENTION NETWORKS(GAT)图注意力网络
摘要: 我们提出一个图注意力网络,一个新的用来操作图结构数据的神经网络结构,它利用"蒙面"的自我注意力层来解决基于图卷积以及和它类似结构的短板.通过堆叠一些层,这些层的节点能够参与 ...
- MySql8错误记录.巨坑!File './binlog.index' not found
mysql8存在大小写敏感,若要设置不敏感,需要在mysql初始化时设置:然后库中已有项目存在,mysql备份文件夹后无法重启,还原数据后存在权限问题,更改文件夹权限后,发现仍然不行,将SELinux ...
- modbus通讯协议详解
1.Modbus 协议简介 Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议.通过此协议,控制器相互之间.或控制器经由网络(如以太网)可以和其它设备之间进行通信.Modbus协议使用 ...