1.设备通过TCP/IP协议连接到Windows服务端,并且向服务端发送数据,服务端接收数据之后会使用MySQL进行数据的存储
在这个过程中,设备向服务端发送数据是什么样的组织形式:我是使用自定义的TCP协议包来封装数据,首先是包头和长度这两个字段,来定位这个数据包的边界,之后是命令,来告诉服务器这个数据包是来自哪个设备的数据,之后是以逗号形式隔开的具体数据,有温度,负载和运行速度;
服务器接收到数据之后,解析数据包得到数据,从MySQL数据库连接池中获取MySQL的连接,并且通过ODB的ORM框架,并且为了代码的可读性,ORM框架使用宏来封装增删改查的业务逻辑,这样就插入了完整的数据
2.如何使用MySQL数据库设计这四张表
首先是存储引擎的选择,我使用的是默认的InnoDB存储引擎,因为InnoDB的隔离级别是可重复读,那么对于多线程环境下是能保持数据一致性的;
接着是数据表的范式选择,这对应了数据库表的属性应该怎么设计,我选择的是第三范式:每个元素都具备原子性,每个属性都依赖于主键且不传递依赖,那么我设计设备表的时候就不能添加任务类型和任务名称等等,保证了数据库表设计ACID原则;
并且有三张表与设备表的主键建立外键的联系,来避免数据的不一致的问题;
最后是索引的添加,我对设备ID来建立索引,这样就能高效的搜索对应的设备已经对应的使用情况
3.如何集成ORM框架的?
我选择的是ODB的ORM框架,因为ODB的书写对于我来说是更加直观并且方便封装宏语句的
ORM框架的封装是配合MySQL连接池来使用的,那么就需要一个队列来存储MySQL的连接的智能指针,使用互斥锁和信号量来维护MySQL连接池的线程安全和资源安全,之后就是封装ORM框架类,配合使用odb编译生成的C++类(实现数据库表映射为对象)和MySQL数据库连接池来进行业务的处理,比如提交和查找
4.设备管理模块
采用IOCP来实现IOCP管理类,含有生产者消费者缓冲区和线程池;就是采用一个线程来启动IOCP接收任务的队列,采用另一个线程来调用IOCP管理类的执行任务
1. 设备表(devices)
设备表存储设备的基本信息。
CREATE TABLE devices (
device_id INT AUTO_INCREMENT PRIMARY KEY, -- 设备ID,主键
device_name VARCHAR(100) NOT NULL, -- 设备名称
device_type VARCHAR(50), -- 设备类型
location VARCHAR(100) -- 设备位置
);
2. 设备运行日志表(device_logs)
设备运行日志表记录设备的运行状态和时间信息。
CREATE TABLE device_logs (
log_id INT AUTO_INCREMENT PRIMARY KEY, -- 日志ID,主键
device_id INT NOT NULL, -- 设备ID,外键
log_time DATETIME NOT NULL, -- 日志时间
status VARCHAR(50), -- 设备状态
FOREIGN KEY (device_id) REFERENCES devices(device_id) -- 外键关联设备表
);
3. 任务状态表(task_statuses)
任务状态表记录与设备相关的任务状态信息。
CREATE TABLE task_statuses (
task_id INT AUTO_INCREMENT PRIMARY KEY, -- 任务ID,主键
device_id INT NOT NULL, -- 设备ID,外键
task_description VARCHAR(255), -- 任务描述
status VARCHAR(50), -- 任务状态
start_time DATETIME, -- 任务开始时间
end_time DATETIME, -- 任务结束时间
FOREIGN KEY (device_id) REFERENCES devices(device_id) -- 外键关联设备表
);
4. 故障信息表(faults)
故障信息表记录设备故障的相关信息。
CREATE TABLE faults (
fault_id INT AUTO_INCREMENT PRIMARY KEY, -- 故障ID,主键
device_id INT NOT NULL, -- 设备ID,外键
fault_description VARCHAR(255), -- 故障描述
fault_time DATETIME NOT NULL, -- 故障发生时间
resolved BOOLEAN DEFAULT FALSE, -- 故障是否已解决
FOREIGN KEY (device_id) REFERENCES devices(device_id) -- 外键关联设备表
);
-
设备表(devices):
- 设备ID (
device_id
) 是主键,唯一标识每个设备。 - 设备名称、设备类型和位置都是设备的基本属性。
- 设备ID (
-
设备运行日志表(device_logs):
- 日志ID (
log_id
) 是主键。 - 设备ID (
device_id
) 是外键,关联到设备表,表示该日志记录对应的设备。 - 日志时间和设备状态是该表的属性。
- 日志ID (
-
任务状态表(task_statuses):
- 任务ID (
task_id
) 是主键。 - 设备ID (
device_id
) 是外键,关联到设备表,表示该任务对应的设备。 - 任务描述、状态、开始时间和结束时间是该表的属性。
- 任务ID (
-
故障信息表(faults):
- 故障ID (
fault_id
) 是主键。 - 设备ID (
device_id
) 是外键,关联到设备表,表示该故障对应的设备。 - 故障描述、故障发生时间和是否已解决是该表的属性。
- 故障ID (
具体问题和 SQL 语句
- 确保设备唯一性
问题:在设备表中插入重复的设备ID会导致数据不一致。
SQL 语句:
INSERT INTO devices (device_id, device_name, device_type) VALUES (1, ‘设备A’, ‘类型1’);
— 尝试插入重复的设备ID
INSERT INTO devices (device_id, device_name, device_type) VALUES (1, ‘设备B’, ‘类型2’);
— 这条语句将会失败,因为device_id是主键,不能重复。
- 确保日志记录的引用完整性
问题:在设备运行日志表中插入一个不存在的设备ID将导致数据不一致。
SQL 语句:
— 插入一条设备日志记录
INSERT INTO device_logs (log_id, device_id, log_time, log_message) VALUES (1, 1, NOW(), ‘设备正常运行’);
— 尝试插入一条日志记录,引用不存在的设备ID
INSERT INTO device_logs (log_id, device_id, log_time, log_message) VALUES (2, 999, NOW(), ‘设备故障’);
— 这条语句将会失败,因为device_id=999在设备表中不存在。
- 关联设备和任务状态
问题:在任务状态表中插入一个不存在的设备ID将导致数据不一致。
SQL 语句:
— 插入一条任务状态记录
INSERT INTO task_statuses (task_id, device_id, task_status, start_time, end_time) VALUES (1, 1, ‘完成’, NOW(), NOW());
— 尝试插入一条任务状态记录,引用不存在的设备ID
INSERT INTO task_statuses (task_id, device_id, task_status, start_time, end_time) VALUES (2, 999, ‘进行中’, NOW(), NULL);
— 这条语句将会失败,因为device_id=999在设备表中不存在。
- 记录故障信息并保持引用完整性
问题:在故障信息表中插入一个不存在的设备ID将导致数据不一致。
SQL 语句:
— 插入一条故障记录
INSERT INTO faults (fault_id, device_id, fault_description, fault_time) VALUES (1, 1, ‘设备出现故障’, NOW());
— 尝试插入一条故障记录,引用不存在的设备ID
INSERT INTO faults (fault_id, device_id, fault_description, fault_time) VALUES (2, 999, ‘设备无法启动’, NOW());
— 这条语句将会失败,因为device_id=999在设备表中不存在。
- 查询设备及其相关信息
问题:需要查询某个设备的运行日志、任务状态和故障信息。
SQL 语句:
— 查询设备及其所有相关信息
SELECT
d.device_name,
dl.log_time,
dl.log_message,
ts.task_status,
ts.start_time,
ts.end_time,
f.fault_description,
f.fault_time
FROM
devices d
LEFT JOIN
device_logs dl ON d.device_id = dl.device_id
LEFT JOIN
task_statuses ts ON d.device_id = ts.device_id
LEFT JOIN
faults f ON d.device_id = f.device_id
WHERE
d.device_id = 1; — 这里可以替换为需要查询的设备ID