想把前端通过网页上传的文件写入 mysql,后台用的公司的框架(基于 spring+mybatis),数据库表字段类型用 longblob,实体类字段类型用 byte[];
文件较小的时候读写都没问题,但文件稍微大点写入就报错,试了下大概大于 128M 就不行了
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
...(从这里开始的报错来自框架)
通过本地调试,发现后台在接收完文件准备写入数据库阶段报错,在这阶段任务管理器的"java.exe"进程从 1000MB+飙到 2000MB+,试着添加 JVM 参数-Xmx2048m 还是不行…
我才写入一个 100M+的文件怎么内存就占这么多了… mysql 的 longblob 可以存 4G,这么大的文件一般是怎么读写的啊?有没有办法像流那样从开始接收文件时就写入数据库,边读边写,并且可以事务控制?
求大佬给点思路或者有没有现成的轮子可以用…
1
kaneg 2019-05-09 11:20:56 +08:00 via iPhone
你估计把整个文件读到内存了,内存在对象传递过程中可能还要复制来复制去,所以最终比文件大。你要做的就是用分段或者流式写入数据库。
|
2
wc951 2019-05-09 12:18:42 +08:00 via Android
byte[]改成 blob 用流
|
3
wc951 2019-05-09 12:21:34 +08:00 via Android
更好的办法是数据库存文件路径,文件单独存储,不管是磁盘存储还是 dfs 都可以
|
4
gz911122 2019-05-09 12:25:31 +08:00 1
文件请存 oss,
数据库保留路径就可以了 |
5
momocraft 2019-05-09 12:27:31 +08:00
jdbc 可以绑 InputStream 为 SQL 参数
|
6
fhsan 2019-05-09 12:39:09 +08:00
文件肯定存到本地、HDFS、云硬盘之类的,怎么会有写入数据库这种操作?我以前的公司有人就喜欢存 JSON 到数据库,每次查询都卡爆。
|
7
opengps 2019-05-09 13:04:05 +08:00
文件为啥要写入数据库?
|
8
ASpiral OP |
10
opengps 2019-05-09 14:25:45 +08:00
@ASpiral 文件写入数据库虽然不排斥,但是也不提倡。
大文件读写很占用的连接比较久,而且文件类往往可能有静态加速等方式,行锁需要担心的问题,在大文件写入时候会暴露的更加明显等 |
11
des 2019-05-09 14:30:04 +08:00
数据库写文件还是不要了吧,更何况还是这么大的文件
|
12
micean 2019-05-09 14:30:22 +08:00
#5 +1
|
13
youxiachai 2019-05-09 14:31:19 +08:00
想起我刚入行的时候......
就有人跟我说,数据库的二进制不是用来纯文件的.... |
14
fhsan 2019-05-09 15:08:34 +08:00
数据库变的巨大,数据库字段的 IO 远远的低于文件系统的 IO,越来越耗时间
文件的备份、还原、查找、内容检索等等,也成了一大问题 如果文件频繁读写增删改查数据,你的数据库立马就崩掉,即使不崩也无法处理大的负载 数据库锁的问题,如果一个人修改字段会阻塞其他读的,直接 500 超时 |
15
ASpiral OP @all 感谢各位的建议!
跟领导反馈了,领导的意见是先实现了再说,毕竟这是客户需求 以后应该是另建一个数据库放文件存储的表,单独一台服务器,后台跟数据库服务器都在内网 领导建议我文件分块写入数据库,存做多条记录,我该研究怎么分块写入跟取出了… |
16
sonyxperia 2019-05-10 16:41:08 +08:00
百兆的文件写入数据库= =
客户的要求也不能都答应啊 |