『7x24小时有问必答』
副标题
: 让数据"留得住、查得到、用得好"

一、PLC与数据库通信的本质

数据库是工业数据的"仓库"——PLC采集数据,数据库存储数据。
[tr][td]传统方式[/td][td]数据库方式[/td][/tr][tr][td]数据存储在PLC[/td][td]数据存储在数据库[/td][/tr][tr][td]掉电数据丢失[/td][td]掉电数据保留[/td][/tr][tr][td]查询困难[/td][td]SQL查询,灵活高效[/td][/tr][tr][td]无历史追溯[/td][td]完整历史记录[/td][/tr]
核心价值
数据持久化:掉电不丢失
历史追溯:查询任意时间点的数据
数据分析:SQL聚合、统计、趋势分析
多系统共享:MES/ERP/SCADA都可以访问
合规性:满足ISO/FDA等合规要求

二、通信架构

2.1 常见架构

架构1:PLC → OPC UA → 数据库
PLC ──OPC UA── 数据采集服务 ──SQL── 数据库
架构2:PLC → 边缘网关 → 数据库
PLC ──Ethernet── 边缘网关 ──SQL/HTTP── 数据库
架构3:PLC → SCADA → 数据库
PLC ──SCADA── SCADA服务器 ──内置── 数据库

2.2 数据库选型

[tr][td]数据库[/td][td]特点[/td][td]适用场景[/td][/tr][tr][td]MySQL[/td][td]开源,易用[/td][td]一般场景[/td][/tr][tr][td]PostgreSQL[/td][td]开源,功能强[/td][td]复杂查询[/td][/tr][tr][td]SQL Server[/td][td]商业,集成好[/td][td]Windows生态[/td][/tr][tr][td]InfluxDB[/td][td]时序数据库[/td][td]时序数据[/td][/tr][tr][td]TimescaleDB[/td][td]时序+SQL[/td][td]时序+关系[/td][/tr]

2.3 数据表设计

生产数据表
CREATE TABLE production_data (
id INT PRIMARY KEY AUTO_INCREMENT,
timestamp DATETIME NOT NULL,
device_id VARCHAR(50) NOT NULL,
temperature FLOAT,
pressure FLOAT,
speed FLOAT,
status VARCHAR(20),
quality_flag INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_timestamp ON production_data(timestamp);
CREATE INDEX idx_device ON production_data(device_id);
报警数据表
CREATE TABLE alarm_data (
id INT PRIMARY KEY AUTO_INCREMENT,
timestamp DATETIME NOT NULL,
device_id VARCHAR(50) NOT NULL,
alarm_code INT NOT NULL,
alarm_level INT,
alarm_message VARCHAR(255),
acknowledged INT DEFAULT 0,
acknowledged_at DATETIME,
acknowledged_by VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

三、数据采集方式

3.1 轮询采集

优点
:简单可靠
缺点
:实时性差,带宽占用大
import mysql.connector
import time

连接数据库

conn = mysql.connector.connect(
host='192.168.3.100',
user='plc_user',
password='password',
database='factory_db'
)
cursor = conn.cursor()

轮询采集

while True:
# 读取PLC数据
temp = read_plc_register('D100')
pressure = read_plc_register('D101')
status = read_plc_register('M100')
# 写入数据库
sql = """
INSERT INTO production_data
(timestamp, device_id, temperature, pressure, status)
VALUES (%s, %s, %s, %s, %s)
"""
cursor.execute(sql, (
time.strftime('%Y-%m-%d %H:%M:%S'),
'PLC01',
temp,
pressure,
'running' if status else 'stopped'
))
conn.commit()
time.sleep(1)  # 1秒采集一次

3.2 事件触发采集

优点
:实时性好,节省带宽
缺点
:实现复杂
# 事件触发采集
def on_alarm(alarm_code, alarm_level, message):
sql = """
INSERT INTO alarm_data
(timestamp, device_id, alarm_code, alarm_level, alarm_message)
VALUES (%s, %s, %s, %s, %s)
"""
cursor.execute(sql, (
time.strftime('%Y-%m-%d %H:%M:%S'),
'PLC01',
alarm_code,
alarm_level,
message
))
conn.commit()

PLC报警时触发

PLC_OnAlarm(on_alarm)

3.3 批量采集

优点
:效率高,减少数据库压力
缺点
:实时性稍差
# 批量采集(每10秒一次)
data_buffer = []
def collect_data():
data_buffer.append({
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
'device_id': 'PLC01',
'temperature': read_plc_register('D100'),
'pressure': read_plc_register('D101'),
'speed': read_plc_register('D102'),
'status': 'running'
})
if len(data_buffer) >= 10:  # 满10条批量插入
sql = """
INSERT INTO production_data
(timestamp, device_id, temperature, pressure, speed, status)
VALUES %s
"""
cursor.executemany(sql, data_buffer)
conn.commit()
data_buffer.clear()

每秒调用一次

every_second(collect_data)

四、PLC侧实现

4.1 三菱PLC + 边缘网关

边缘网关配置
[tr][td]参数[/td][td]设置[/td][/tr][tr][td]PLC连接[/td][td]Ethernet, IP=192.168.3.1[/td][/tr][tr][td]数据库连接[/td][td]MySQL, IP=192.168.3.100[/td][/tr][tr][td]采集周期[/td][td]1秒[/td][/tr][tr][td]批量大小[/td][td]10条[/td][/tr][tr][td]重试次数[/td][td]3次[/td][/tr]

4.2 ST语言实现(边缘网关)

( 数据采集到数据库 )
VAR
( 数据库连接 )
DB_Conn: MySQL_Connection;
DB_Status: INT;
( 采集数据 )
Temp_Current: REAL;
Pressure_Current: REAL;
Speed_Current: REAL;
Motor_Status: BOOL;
( 缓冲区 )
Data_Buffer: ARRAY[0..9] OF STRUCT
Timestamp: STRING;
Device_ID: STRING;
Temperature: REAL;
Pressure: REAL;
Speed: REAL;
Status: STRING;
END_STRUCT;
Buffer_Count: INT := 0;
( 定时器 )
Collect_Timer: TON;
Batch_Timer: TON;
END_VAR
( 每秒采集数据 )
Collect_Timer(IN:=TRUE, PT:=T#1s);
IF Collect_Timer.Q THEN
( 读取PLC数据 )
Temp_Current := PLC_ReadReal('D100');
Pressure_Current := PLC_ReadReal('D101');
Speed_Current := PLC_ReadReal('D102');
Motor_Status := PLC_ReadBool('M100');
( 存入缓冲区 )
Data_Buffer[Buffer_Count].Timestamp := Get_TimeString();
Data_Buffer[Buffer_Count].Device_ID := 'PLC01';
Data_Buffer[Buffer_Count].Temperature := Temp_Current;
Data_Buffer[Buffer_Count].Pressure := Pressure_Current;
Data_Buffer[Buffer_Count].Speed := Speed_Current;
Data_Buffer[Buffer_Count].Status := IF(Motor_Status, 'running', 'stopped');
Buffer_Count := Buffer_Count + 1;
IF Buffer_Count >= 10 THEN
( 批量写入数据库 )
DB_BatchInsert(DB_Conn, 'production_data', Data_Buffer, 10);
Buffer_Count := 0;
END_IF;
Collect_Timer(IN:=FALSE);
END_IF;

五、深度案例分析:注塑机生产数据追溯

5.1 背景

某注塑厂需要满足ISO9001要求,实现生产数据完整追溯。

5.2 问题经过

[tr][td]问题[/td][td]表现[/td][td]影响[/td][/tr][tr][td]数据丢失[/td][td]PLC掉电数据丢失[/td][td]无法追溯[/td][/tr][tr][td]查询困难[/td][td]无统一数据库[/td][td]效率低[/td][/tr][tr][td]无历史趋势[/td][td]无法分析[/td][td]无法优化[/td][/tr][tr][td]合规风险[/td][td]无完整记录[/td][td]ISO审核不通过[/td][/tr]

5.3 解决方案

数据采集架构
┌─────────────────────────────────────────────────────────┐
│                    数据采集层                            │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐                │
│  │注塑机1  │  │注塑机2  │  │注塑机3  │                │
│  │ (PLC)   │  │ (PLC)   │  │ (PLC)   │                │
│  └────┬────┘  └────┬────┘  └────┬────┘                │
│       │            │            │                      │
│  ┌────┴────┐  ┌────┴────┐  ┌────┴────┐                │
│  │边缘网关 │  │边缘网关 │  │边缘网关 │                │
│  │(数据采集)│  │(数据采集)│  │(数据采集)│                │
│  └────┬────┘  └────┬────┘  └────┬────┘                │
│       │            │            │                      │
├───────┼────────────┼────────────┼──────────────────────┤
│       │            │            │                      │
│  ┌────┴────────────┴────────────┴────┐                │
│  │           MySQL 数据库             │                │
│  │  - 生产数据表  - 报警数据表       │                │
│  │  - 质量数据表  - 配方数据表       │                │
│  └───────────────────────────────────┘                │
│                           │                             │
│                           ▼                             │
│  ┌───────────────────────────────────┐                │
│  │        Web追溯系统                │                │
│  │  - 生产记录查询  - 质量追溯       │                │
│  │  - 趋势分析  - 报表生成           │                │
│  └───────────────────────────────────┘                │
└─────────────────────────────────────────────────────────┘
数据表设计
-- 生产记录表
CREATE TABLE injection_production (
id INT PRIMARY KEY AUTO_INCREMENT,
machine_id VARCHAR(20) NOT NULL,
product_id VARCHAR(50) NOT NULL,
batch_no VARCHAR(50) NOT NULL,
cycle_time FLOAT,
injection_pressure FLOAT,
holding_pressure FLOAT,
mold_temp FLOAT,
product_weight FLOAT,
quality_flag INT,
start_time DATETIME,
end_time DATETIME,
operator VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 质量检验表
CREATE TABLE quality_inspection (
id INT PRIMARY KEY AUTO_INCREMENT,
production_id INT,
check_time DATETIME,
dimension_1 FLOAT,
dimension_2 FLOAT,
surface_quality INT,
result INT,  -- 0:合格, 1:不合格
inspector VARCHAR(50),
remark VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

5.4 效果对比

[tr][td]指标[/td][td]优化前[/td][td]优化后[/td][td]提升[/td][/tr][tr][td]数据保留[/td][td]掉电丢失[/td][td]永久保存[/td][td]100%[/td][/tr][tr][td]查询时间[/td][td]30分钟[/td][td]<10秒[/td][td]-99%[/td][/tr][tr][td]追溯精度[/td][td]无法追溯[/td][td]精确到每个产品[/td][td]100%[/td][/tr][tr][td]ISO审核[/td][td]不通过[/td][td]通过[/td][td]通过[/td][/tr][tr][td]质量分析[/td][td]无法分析[/td][td]实时分析[/td][td]显著提升[/td][/tr]

六、SQL查询示例

6.1 实时查询

-- 查询当前生产状态
SELECT machine_id, product_id, cycle_time, quality_flag
FROM injection_production
WHERE end_time > NOW() - INTERVAL 1 HOUR
ORDER BY end_time DESC;

6.2 历史查询

-- 查询某批次生产记录
SELECT * FROM injection_production
WHERE batch_no = 'B20260604001'
ORDER BY start_time;

6.3 统计分析

-- 查询各机台产量
SELECT machine_id, COUNT(*) as total, AVG(cycle_time) as avg_cycle
FROM injection_production
WHERE DATE(start_time) = '2026-06-04'
GROUP BY machine_id;
-- 查询质量合格率
SELECT
machine_id,
COUNT(*) as total,
SUM(CASE WHEN quality_flag = 0 THEN 1 ELSE 0 END) as passed,
SUM(CASE WHEN quality_flag = 0 THEN 1 ELSE 0 END) 100.0 / COUNT() as pass_rate
FROM injection_production
WHERE DATE(start_time) = '2026-06-04'
GROUP BY machine_id;

6.4 趋势分析

-- 查询温度趋势
SELECT
DATE_FORMAT(start_time, '%Y-%m-%d %H:%i') as time_slot,
AVG(mold_temp) as avg_temp,
MIN(mold_temp) as min_temp,
MAX(mold_temp) as max_temp
FROM injection_production
WHERE start_time BETWEEN '2026-06-04 00:00:00' AND '2026-06-04 23:59:59'
GROUP BY time_slot
ORDER BY time_slot;

七、常见问题排查

7.1 连接问题

[tr][td]问题[/td][td]可能原因[/td][td]解决方案[/td][/tr][tr][td]无法连接[/td][td]网络不通[/td][td]检查网络连通性[/td][/tr][tr][td]认证失败[/td][td]用户名密码错误[/td][td]检查数据库认证[/td][/tr][tr][td]数据库不存在[/td][td]库名错误[/td][td]检查数据库名[/td][/tr]

7.2 数据问题

[tr][td]问题[/td][td]可能原因[/td][td]解决方案[/td][/tr][tr][td]数据不写入[/td][td]SQL错误[/td][td]检查SQL语法[/td][/tr][tr][td]数据重复[/td][td]重复提交[/td][td]增加唯一约束[/td][/tr][tr][td]数据缺失[/td][td]采集中断[/td][td]检查采集服务[/td][/tr]

八、核心工具推荐

8.1 数据库

[tr][td]数据库[/td][td]适用场景[/td][/tr][tr][td]MySQL[/td][td]通用,开源[/td][/tr][tr][td]PostgreSQL[/td][td]复杂查询,开源[/td][/tr][tr][td]InfluxDB[/td][td]时序数据,开源[/td][/tr][tr][td]SQL Server[/td][td]Windows生态,商业[/td][/tr]

8.2 开发工具

[tr][td]工具[/td][td]用途[/td][/tr][tr][td]MySQL Workbench[/td][td]MySQL管理[/td][/tr][tr][td]DBeaver[/td][td]通用数据库管理[/td][/tr][tr][td]Navicat[/td][td]通用数据库管理[/td][/tr]

九、金句集锦

本文基于三菱PLC与MySQL数据库通信实战经验整理,涵盖数据采集、表设计、SQL查询、注塑机追溯案例等核心主题。
推荐阅读
三菱GX Works3 028:安全PLC编程——SIL2/SIL3安全功能实战
发布于 2026-05-27
三菱 PLC 教程 02:iQ-R 系列硬件组成
发布于 202603
NACHI 机械手教程第 4 章:编程基础
发布于 202603
KEYWORDS
PLC, plc, SCADA, 三菱
如果你觉得这篇文章有帮助,请点个在看,分享给更多需要的人!
关注我,获取更多实用干货~
有问题欢迎评论区留言交流!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码