数据库与图片完美解决方案

数据库与图片完美解决方案

电商商品图品与数据库脏数据完美解决方案

摘要

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


目录

  • 1. 背景
  • 2. 解决思路
  • 3. 解决方案
  • 4. plugin 的开发与使用
  • 5. 在事务中使用该插件
  • 6. 通过触发器调用图片处理函数

1. 背景

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

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

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

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

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

2. 解决思路

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

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 直接穿插使用,实现在事物处理期间做你爱做的事。

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;		

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');		

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

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

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

触发器进一步优化

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

原文发布于微信公众号 - Netkiller(netkiller-ebook)

原文发表时间:2015-09-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大闲人柴毛毛

缓存世界中的三大问题及解决方案

目前的IO设备远不能满足互联网应用海量的读写请求。于是便出现了缓存,利用内存的高速读写性能来应付海量的查询请求。然而内存资源非常宝贵,将全量数据存储在内存中显...

2755
来自专栏施炯的IoT开发专栏

Application Architecture Guide 2.0 - CH 19 - Mobile Applications(5)

本文翻译"Deployment"、"Pattern Map"、"Pattern Descriptions"和"Technology Considerations...

1837
来自专栏写代码的海盗

Nodejs课堂笔记-第四课 Dynamodb为何物

本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢!   我喜欢带着目标来学习...

2735
来自专栏Netkiller

数据库与图片完美解决方案

数据库与图片完美解决方案 电商商品图品与数据库脏数据完美解决方案 摘要 你是是不是在开发中常常遇到,删除了数据库记录后,发现该记录对应的图片没有删除,或者删除了...

2995
来自专栏美团技术团队

【技术博客】Cache应用中的服务过载案例研究

简单地说,过载是外部请求对系统的访问量突然激增,造成请求堆积,服务不可用,最终导致系统崩溃。本文主要分析引入Cache可能造成的服务过载,并讨论相关的预防、恢复...

2955
来自专栏JAVA高级架构

大型高并发与高可用的三层缓存架构总结

对于高并发架构,毫无疑问缓存是最重要的一环,对于大量的高并发,可以采用三层缓存架构来实现,nginx+redis+ehcache nginx ? 对于中间件ng...

4107
来自专栏数据库

分布式高并发下mysql数据库读写分离

读写 分离(Read/Write Splitting)。 1.原理:让主数据库(master)处理事务性增、改、删操作(INSERT、UPDATE、DELETE...

3978
来自专栏程序人生 阅读快乐

MySQL技术内幕(第4版) - 杜波依斯

由杜波依斯编著的《MySQL技术内幕(第4版)》介绍了MySQL的基础知识及其有别于其他数据库系统的独特功能,包括SQL的工作原理和MySQL API的相关知识...

431
来自专栏鹅厂优文

鹅厂优文 | 企点PC端性能测试-UI卡顿分析

本文以一个企点融合工作台测试中发现的案例说明如何获得UI卡顿数据,以及如何分析数据,定位问题。

92112
来自专栏熊二哥

快速入门系列--Log4net日志组件

Log4net是阿帕奇基金会的非常流行的开源日志组件,是log4j的.NET移植版本,至今已经有11年的历史,使用方便并且非常稳定,此外很重要的一点是其和很多开...

18810

扫码关注云+社区