1. 程式人生 > 其它 >資料庫與圖片完美解決方案

資料庫與圖片完美解決方案

資料庫與圖片完美解決方案

電商商品圖品與資料庫髒資料完美解決方案

摘要

你是是不是在開發中常常遇到,刪除了資料庫記錄後,發現該記錄對應的圖片沒有刪除,或者刪除了圖片,資料庫中仍有資料存在,你的網站髒資料(圖片)成幾何數增長,閱讀下文這裡為你提供了一個完美決方案。


目錄

  • 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% 保險