資料庫與圖片完美解決方案
資料庫與圖片完美解決方案
電商商品圖品與資料庫髒資料完美解決方案
摘要
你是是不是在開發中常常遇到,刪除了資料庫記錄後,發現該記錄對應的圖片沒有刪除,或者刪除了圖片,資料庫中仍有資料存在,你的網站髒資料(圖片)成幾何數增長,閱讀下文這裡為你提供了一個完美決方案。
目錄
- 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% 保險