8.3. 数据库与外界文件

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

你是是不是在开发中常常遇到,删除了数据库记录后,发现该记录对应的图片没有删除,或者删除了图片,数据库中仍有数据存在,你的网站脏数据(图片)成几何数增长,阅读下文这里为你提供了一个完美决方案。

8.3.1. 背景

我以电商网站为例,一般的网站产品数据存放在数据库中,商品图片是上传到文件服务器,然后通过http服务器浏览商品图片。这是最基本的也是最常见做法。

稍复杂的方案是,如果图片数量庞大,会使用分布式文件系统方案。但是这些方案都不能保证数据的完整性,极易产生脏数据(垃圾数据)。脏数据是指当你删除了数据库表中的记录后,图片仍然存在,或者手工删除了图片,而数据库中的记录仍然存在。

将图片放入数据库中存放在BLOB的方法可以解决脏数据问题,典型的案例是公安的身份证系统。但这种方案的前提是,图片不能太大,数量不多,访问量不大。 这显然不适合电商网站。

2009年我在走秀网工作,商品图片与缩图文件900GB到2012离职已经有10TB,每天有成百上千的商品上架下架,很多商品下架后永远不会再上架,这些批量下架的商品数据不会删除,仅仅标记为删除,总是期望以后能继续使用,实际上再也不会有人过问,另一方面随着品类经理频繁更换,员工离职,这些商品会石沉大海,再也无人问均。这些商品所对应的图片也就脏数据主要来源。新的品类经理上任后,会重新拍照,上传新图片。

总之,删除数据库中的数据不能将图片删除就会产生脏数据。很多采用删除数据的时候去检查图片如果存在先删除图片,再删除数据的方法。这种方案也非完美解决方案,存在这图片先被删除,程序出错SQL没有运行,或者反之。

8.3.2. 解决思路

如果删除图片能够成为事物处理中的一个环节,所有问题都能迎刃而解,可彻底解决脏数据的烦恼。

8.3.3. 解决方案

mysql plugin 开发 udf。我写几个function

UDF

image_check(filename)

检查图片是否存在.

image_remove(filename)

删除图片.

image_rename(oldfile,newfile)

更改图片文件名.

image_md5sum(filename)

md5sum 主要用户图片是否被更改过.

image_move(filename,filename)

移动图片的位置

有了上面的function后你就可以在begin,commit,rollback 直接穿插使用,实现在事物处理期间做你爱做的事。

8.3.4. plugin 的开发与使用

编译UDF你需要安装下面的软件包

sudo apt-get install pkg-config
sudo apt-get install libmysqlclient-dev

sudo apt-get install gcc gcc-c++ make automake autoconf
		

https://github.com/netkiller/mysql-image-plugin

编译udf,最后将so文件复制到 /usr/lib/mysql/plugin/

git clone https://github.com/netkiller/mysql-image-plugin.git
cd mysql-image-plugin/src

gcc -I/usr/include/mysql -I./ -fPIC -shared -o image.so image.c
sudo mv image.so /usr/lib/mysql/plugin/
		

装载

create function image_check returns boolean soname 'images.so';
create function image_remove returns boolean soname 'images.so';
create function image_rename returns boolean soname 'images.so';
create function image_md5sum returns string soname 'images.so';
create function image_move returns string soname 'images.so';
		

卸载

drop function image_check;
drop function image_remove;
drop function image_rename;
drop function image_md5sum;
drop function image_move;
		

8.3.5. 在事务中使用该插件

插入图片流程,上传图片后,通过插件检查图片是否正确上传,然后插入记录

begin;
IF image_check('/path/to/images.jpg') THEN
	insert into images(product_id,thumbnail,original) values(1000,'thumbnail/path/to/images.jpg','original/path/to/images.jpg');
	commit;
ELSE
	image_remove('/path/to/images.jpg');
END IF
rollback;
		

删除商品采用image_move 方案,当出现异常rollback后还可以还原被删除的图片

begin;
IF image_check('/path/to/images.jpg') THEN
	select thumbnail,original into @thumbnail,@original from images where id='1000' for delete;
	delete from images where id='1000';
	select image_move(@thumbnail,'recycle/path/to/');
	select image_move(@original,'recycle/path/to/');
	commit;
END IF

rollback;
select image_move('recycle/path/to/images.jpg','path/to/images.jpg');
		

我们可以使用EVENT定时删除回收站内的图片

image_remove('recycle/path/to/images.jpg');
		

8.3.6. 通过触发器调用图片处理函数

通过触发器更能保证数据完整性

1. insert 触发器的任务: 插入记录的时候通过image_check检查图片是否正常上传,如果非没有上传,数据插入失败。
2. delete 触发器的任务: 检查删除记录的时候,首先去删除图片,删除成功再删除该记录。
		

触发器进一步优化

1. insert 触发器的任务: 插入记录的时候通过image_check检查图片是否正常上传,如果非没有上传,数据插入失败。如果上传成功再做image_md5sum 进行校验100% 正确后插入记录
2. delete 触发器的任务: 检查删除记录的时候,首先去改图片文件名,然后删除该记录,最后删除图片,删除成功。如果中间环境失败 记录会rollback,图片会在次修改文件名改回来。100% 保险
	





原文出处:Netkiller 系列 手札
本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
26198
分享
相关文章
数据库数据恢复—MongoDB数据库迁移过程中丢失文件的数据恢复案例
某单位一台MongoDB数据库由于业务需求进行了数据迁移,数据库迁移后提示:“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
数据库导入SQL文件:全面解析与操作指南
在数据库管理中,将SQL文件导入数据库是一个常见且重要的操作。无论是迁移数据、恢复备份,还是测试和开发环境搭建,掌握如何正确导入SQL文件都至关重要。本文将详细介绍数据库导入SQL文件的全过程,包括准备工作、操作步骤以及常见问题解决方案,旨在为数据库管理员和开发者提供全面的操作指南。一、准备工作在导
1022 0
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
数据库数据恢复—Oracle数据库文件出现坏块的数据恢复案例
打开oracle数据库报错“system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。 数据库没有备份,无法通过备份去恢复数据库。用户方联系北亚企安数据恢复中心并提供Oracle_Home目录中的所有文件,急需恢复zxfg用户下的数据。 出现“system01.dbf需要更多的恢复来保持一致性”这个报错的原因可能是控制文件损坏、数据文件损坏,数据文件与控制文件的SCN不一致等。数据库恢复工程师对数据库文件进一步检测、分析后,发现sysaux01.dbf文件损坏,有坏块。 修复并启动数据库后仍然有许多查询报错,export和data pump工具使用报错。从数据库层面无法修复数据库。
数据库数据恢复—Oracle数据库文件出现坏块的数据恢复案例
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
147 2
SQL文件导入MySQL数据库的详细指南
数据库中的数据转移是一项常规任务,无论是在数据迁移过程中,还是在数据备份、还原场景中,导入导出SQL文件显得尤为重要。特别是在使用MySQL数据库时,如何将SQL文件导入数据库是一项基本技能。本文将详细介绍如何将SQL文件导入MySQL数据库,并提供一个清晰、完整的步骤指南。这篇文章的内容字数大约在
736 1
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第3天】Spring Boot项目中数据库连接问题可能源于配置错误或依赖缺失。YAML配置文件的格式不正确,如缩进错误,会导致解析失败;而数据库驱动不匹配、连接字符串或认证信息错误同样引发连接异常。解决方法包括检查并修正YAML格式,确认配置属性无误,以及添加正确的数据库驱动依赖。利用日志记录和异常信息分析可辅助问题排查。
716 10

热门文章

最新文章