我遇到了使用Hibernate / MySQL的Spring Boot应用程序的问题。
应用程序接收传感器数据(每秒最多多次)并将传入数据保存为Hibernate实体。您可以在下面找到传感器日志实体的Java代码。
系统部署在Raspberry Pi上,后者使用SD卡作为内存。看起来非常(!)的大量写入操作会对SD卡造成太大压力而且会失败。开发Pi上使用的最后一张SD卡虽然质量很高,却持续了大约6个月。
我想减少每秒/分钟的写入次数。最理想的是,数据每5或10分钟保存一次。在电力短缺的情况下数据丢失不是问题。我已经研究过硬件解决方案,比如使用外部硬盘驱动器来存储数据库。我唯一的选择是使用RPi的SD卡。所以我的方法是通过配置Spring / Hibernate / MySQL来减少写操作。然而,经过一些研究后,我发现有一些不同的方法来实现这一目标,我不确定哪一种最适合我的需求。
1。幼稚
我可以编写一个接受实体并将它们存储到列表中的Spring组件,然后定期保存列表内容。这似乎是相当多的编程工作,我希望有一些方法可以更智能地实现这一点。
2。冬眠/ MySQL的/ InnoDB的
我发现InnoDB配置sysvar_innodb_flush_log_at_trx_commit看起来像我想做的那样。我可以使用这个配置让mysql连接每1秒只刷新一次,但这不是最佳的:
我确信有一种方法可以直接在Hibernate中定义这种行为,但我还没有找到它。
结论/问题
有没有办法达到预期的行为?基于快速研究的建议是否有意义,或者您有更好的建议可供调查?非常感谢有关此事的任何意见!
附录:实体代码:
@Table(
name = "sensor_data_point",
indexes = { @Index(name = "sdp_idx", columnList = "sensor_uid,name,created") }
)
@Entity
@EntityListeners({AuditingEntityListener.class})
public class SensorDataPoint {
@Id
@GeneratedValue
private long id;
@Column(name = "sensor_uid", length = 191)
private String sensorUid;
@Column(name = "name", length = 191)
private String name;
@Column(name = "value", length = 191)
private String value;
@CreatedDate
@Column(name = "created")
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
// Constructor, Getters, Setters
// ...
}
答案 0 :(得分:0)
sync_binlog=OFF
由于您可以丢失一些数据,请考虑以下事项。对于讨论,让我们说你可以丢失1分钟的数据。
有一个名为MEMORY
的额外Gather
表,您可以在其中收集传感器数据,而不是Real
InnoDB表。并且每分钟都有EVENT
或cron
个工作,并执行以下操作:
CREATE TABLE Tmp LIKE Gather; -- copy schema
RENAME TABLE Gather TO Inserter, Tmp TO Gather; -- atomic, fast
INSERT INTO Real SELECT * FROM Inserter; -- batched, single transaction, etc
注意:
SELECT
期间,您可以转换数据(如有必要)。此外:
MEMORY
,因为它符合您的情况。innodb_flush_log_at_trx_commit
请提供生成的SHOW CREATE TABLE
和INSERT
代码的SQL。可能会有更多建议给你。有多少传感器? diff行或diff cols中的传感器值是否不同?等