问题描述
数据库存图片路径,现在要删除N条记录,怎么能保证数据的一致性?删除记录的时候也要删除图片。
解决方案
解决方案二:
挂接主外键关系,根据主键删除
解决方案三:
引用1楼linux_010的回复:
挂接主外键关系,根据主键删除
跟我问的问题没关系吧我是说你是先删除数据还是先删除文件呢?如果先删除文件,删数据的时候出异常,那么你文件就没了,如果你先删数据,删文件的时候你数据就没了。。。。
解决方案四:
很简单,建立一个事务,然后再删除数据的时候,先校验图片是否存在,是否被占用,如果符合这两条则执行删除数据,然后再删除图片,如果图片删除失败则回滚事务,图片删除成功提交事务。如果删除多条则循环。
解决方案五:
楼主是这个意思吗?
解决方案六:
引用3楼lvfeng1989的回复:
很简单,建立一个事务,然后再删除数据的时候,先校验图片是否存在,是否被占用,如果符合这两条则执行删除数据,然后再删除图片,如果图片删除失败则回滚事务,图片删除成功提交事务。如果删除多条则循环。
对然后你提交事务的时候数据库异常了,比如超时。这个时候文件删了数据没了
解决方案七:
删除的时候只是做逻辑删除,数据库事务可以保证一批数据要么同时更新要么不更新。文件也是同理,不是做物理删除,而是通过改文件名或者移动目录的方式以示“删除”。顺序是先“删除”文件,再改数据库。try...catch...catch里面写“恢复”的逻辑代码。
解决方案八:
引用5楼wjfwd2010的回复:
Quote: 引用3楼lvfeng1989的回复:
很简单,建立一个事务,然后再删除数据的时候,先校验图片是否存在,是否被占用,如果符合这两条则执行删除数据,然后再删除图片,如果图片删除失败则回滚事务,图片删除成功提交事务。如果删除多条则循环。对然后你提交事务的时候数据库异常了,比如超时。这个时候文件删了数据没了
说错了是这个时候你文件删了,数据还在。
解决方案九:
楼主你这是硬性问题了,你怎么不说文件删除了,删除数据的时候突然断电呢。如果按照你这种说法没有办法避免,如果数据库异常你怎么让程序进行处理。
解决方案十:
那你先删数据再删图片不就好了,数据删除出错回滚很正常,但你要无法删除物理盘上的文件如何也说不过去,不是你服务器磁盘出问题就是你程序有BUG了
解决方案十一:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?
解决方案十二:
引用8楼lvfeng1989的回复:
楼主你这是硬性问题了,你怎么不说文件删除了,删除数据的时候突然断电呢。如果按照你这种说法没有办法避免,如果数据库异常你怎么让程序进行处理。
断电了,数据库也有保护机制的,跟我说的异常是一致的。这就是我问的问题了。
解决方案十三:
引用10楼lvfeng1989的回复:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?
大哥你先冷静点,首先我知道事务,这里事务对图片是无法回滚的我们举个例子吧我删除图片,成功了,提交事务,会不会出异常呢?答案是肯定的,事务只是保证数据的一致性,不是图片的。。。。
解决方案十四:
你是刚开始做开发的吧。我说了这是硬性问题。没有办法避免
解决方案十五:
引用10楼lvfeng1989的回复:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?
理论上讲,你的做法并不是单一的事务,因为图片删除不是事务的一部分。“...图片删除成功提交事务”,可能出现1、图片删除成功2、提交事务,不成功(网络问题/死机等等)。
解决方案:
引用6楼guwei4037的回复:
删除的时候只是做逻辑删除,数据库事务可以保证一批数据要么同时更新要么不更新。文件也是同理,不是做物理删除,而是通过改文件名或者移动目录的方式以示“删除”。顺序是先“删除”文件,再改数据库。try...catch...catch里面写“恢复”的逻辑代码。
感谢版主的回答,这样做确实能好点,当数据库删除成功以后,物理备份文件,删除失败的问题,这样还是占用磁盘的开销。我能想到的就是在写个程序去遍历删除这个备份文件夹里的文件,删除的时候进制其他操作就行了?
解决方案:
引用13楼lvfeng1989的回复:
你是刚开始做开发的吧。我说了这是硬性问题。没有办法避免
惭愧做了,6,7年了。
解决方案:
总结一下,感觉就是先删除数据,再删除文件,不管文件删除成功与否,再弄个程序遍历删除失效的文件,总不能一直失败。这是我能想到的最好的方案了。
解决方案:
这种做个事后job定时清理吧,可以通过在删的同时写入一个数据表,这样数据库之间可以通过数据库事务,然后job通过这个表去删除图片,这个删除的时候就不需要事务了,就算数据问题,删除成功,但数据没更新,下次再删除也没事(虽然其实已经没文件可以删除了)当然貌似文件也是可以通过分布式事务的,但这个资料之前有看过,现在一时间也找不到了
解决方案:
引用18楼starfd的回复:
这种做个事后job定时清理吧,可以通过在删的同时写入一个数据表,这样数据库之间可以通过数据库事务,然后job通过这个表去删除图片,这个删除的时候就不需要事务了,就算数据问题,删除成功,但数据没更新,下次再删除也没事(虽然其实已经没文件可以删除了)当然貌似文件也是可以通过分布式事务的,但这个资料之前有看过,现在一时间也找不到了
对对我就想要一下类似的资料。
解决方案:
先删除数据库吧数据库删除成功文件删除失败无所谓反正数据库里面也"引用"不到文件了但是如果你先删除文件数据库删除成功那么数据库里面则还保留这一个文件的"引用"而事实上文件已经不存在了如果先删除数据库按照最坏打算数据库全部删除成功文件一个都没有成功对于你的损失而言也就是浪费一点磁盘空间而已。。其实可以对文件用md5作为文件名别人上传的时候先计算md5如果一样就压根不用上传了因为服务器上有。。而别人删除文件的时候你也不用真正的去删除。。不过得看你的业务是什么。。
解决方案:
引用10楼lvfeng1989的回复:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?
一个是存储在磁盘上的文件一个是存储在数据库文件中的一条记录两个不同的东西要一起删除你扯出了所谓的“事物”?。。。谁来给你提供“事物”处理啊?。。是系统还是数据库?。。还是自己写代码?。。引用13楼lvfeng1989的回复:
你是刚开始做开发的吧。我说了这是硬性问题。没有办法避免
弱弱的问一句你又做开发多久了?。。。
解决方案:
引用21楼crystal_lz的回复:
Quote: 引用10楼lvfeng1989的回复:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?一个是存储在磁盘上的文件一个是存储在数据库文件中的一条记录两个不同的东西要一起删除你扯出了所谓的“事物”?。。。谁来给你提供“事物”处理啊?。。是系统还是数据库?。。还是自己写代码?。。引用13楼lvfeng1989的回复:
你是刚开始做开发的吧。我说了这是硬性问题。没有办法避免弱弱的问一句你又做开发多久了?。。。
哎,无语了,这个事务处理是用来判别校验文件的,如果文件删除了才会真正的执行删除操作,如果数据删除成功再去删除文件,文件删除成功去提交事务,他们两个虽然一个在磁盘一个数据库,但是能做到起码的安全,你真的很菜啊。看清楚我的逻辑,我就没打算去恢复文件。
解决方案:
引用21楼crystal_lz的回复:
Quote: 引用10楼lvfeng1989的回复:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?一个是存储在磁盘上的文件一个是存储在数据库文件中的一条记录两个不同的东西要一起删除你扯出了所谓的“事物”?。。。谁来给你提供“事物”处理啊?。。是系统还是数据库?。。还是自己写代码?。。引用13楼lvfeng1989的回复:
你是刚开始做开发的吧。我说了这是硬性问题。没有办法避免弱弱的问一句你又做开发多久了?。。。
你看我哪句话说如果数据删除失败回滚事务并恢复文件了,你也只能弱弱的问吧,太弱了
解决方案:
解决方案:
引用24楼starfd的回复:恩学习了,不过不能用IO操作。。。。
解决方案:
引用22楼lvfeng1989的回复:
Quote: 引用21楼crystal_lz的回复:
Quote: 引用10楼lvfeng1989的回复:
还有楼主看清楚我的回答,我这个是有事务控制的先删除数据,然后再删除图片,如果图片删除失败,数据回滚。你知道事务吗?一个是存储在磁盘上的文件一个是存储在数据库文件中的一条记录两个不同的东西要一起删除你扯出了所谓的“事物”?。。。谁来给你提供“事物”处理啊?。。是系统还是数据库?。。还是自己写代码?。。引用13楼lvfeng1989的回复:
你是刚开始做开发的吧。我说了这是硬性问题。没有办法避免弱弱的问一句你又做开发多久了?。。。
哎,无语了,这个事务处理是用来判别校验文件的,如果文件删除了才会真正的执行删除操作,如果数据删除成功再去删除文件,文件删除成功去提交事务,他们两个虽然一个在磁盘一个数据库,但是能做到起码的安全,你真的很菜啊。看清楚我的逻辑,我就没打算去恢复文件。
实在忍不住多句嘴您别生气啊,那我直接把操作数据库的代码写在删除代码下面不就完了,为什么要用事务多此一举呢?
解决方案:
先把数据备份到一个对象里面,然后删除数据,再删除图片,如果删除图片失败,在把备份的数据插入数据库。
解决方案:
引用6楼guwei4037的回复:
删除的时候只是做逻辑删除,数据库事务可以保证一批数据要么同时更新要么不更新。文件也是同理,不是做物理删除,而是通过改文件名或者移动目录的方式以示“删除”。顺序是先“删除”文件,再改数据库。try...catch...catch里面写“恢复”的逻辑代码。
基本同意这个方法,具体可以移动图片文件的方法代替删除先移动图片文件,再删除数据库,这样不管什么情况都有办法处理至于移动的图片,可以定时删除(删前先检查数据库)
解决方案:
引用25楼wjfwd2010的回复:
Quote: 引用24楼starfd的回复:恩学习了,不过不能用IO操作。。。。
看了一下这个写了一个差不多如下的代码publicclassFileDelTest:IEnlistmentNotification{privateboolm_bExecCommit;privateFileStreamm_fs;privatebyte[]m_byFile;//缓存数据privatestringm_strFileName;publicFileDelTest(stringstrFileName){m_strFileName=strFileName;m_fs=newFileStream(m_strFileName,FileMode.Open);//占用文件先m_byFile=newbyte[m_fs.Length];//先缓存数据m_fs.Read(m_byFile,0,m_byFile.Length);}publicvoidCommit(Enlistmentenlistment){m_fs.Close();//解除文件的占用File.Delete(m_strFileName);//关闭再删除可能会出现一瞬间的巧合enlistment.Done();m_bExecCommit=true;}publicvoidRollback(Enlistmentenlistment){if(m_bExecCommit){//如果已经执行了commit了(有多个这样类的情况部分可能已经执行commit)using(FileStreamfs=newFileStream(m_strFileName,FileMode.Create)){fs.Write(m_byFile,0,m_byFile.Length);//写入回去这里也可能出现一瞬间的巧合}}elsem_fs.Close();//否则直接关闭文件占用enlistment.Done();}...其他实现}try{using(TransactionScopescope=newTransactionScope()){FileDelTestmyElistment=newFileDelTest("D:\123.test");Transaction.Current.EnlistVolatile(myElistment,EnlistmentOptions.None);thrownewException("test");//引发异常跳出using执行回滚scope.Complete();MessageBox.Show("main-OK");}}catch(System.Transactions.TransactionExceptionex){MessageBox.Show("main-"+ex.Message);}catch(Exceptionex){MessageBox.Show("main-"+ex.Message);}
不过还是会出问题的。。。出那一瞬间巧合的问题。。
解决方案:
引用29楼crystal_lz的回复:
Quote: 引用25楼wjfwd2010的回复:
Quote: 引用24楼starfd的回复:恩学习了,不过不能用IO操作。。。。看了一下这个写了一个差不多如下的代码publicclassFileDelTest:IEnlistmentNotification{privateboolm_bExecCommit;privateFileStreamm_fs;privatebyte[]m_byFile;//缓存数据privatestringm_strFileName;publicFileDelTest(stringstrFileName){m_strFileName=strFileName;m_fs=newFileStream(m_strFileName,FileMode.Open);//占用文件先m_byFile=newbyte[m_fs.Length];//先缓存数据m_fs.Read(m_byFile,0,m_byFile.Length);}publicvoidCommit(Enlistmentenlistment){m_fs.Close();//解除文件的占用File.Delete(m_strFileName);//关闭再删除可能会出现一瞬间的巧合enlistment.Done();m_bExecCommit=true;}publicvoidRollback(Enlistmentenlistment){if(m_bExecCommit){//如果已经执行了commit了(有多个这样类的情况部分可能已经执行commit)using(FileStreamfs=newFileStream(m_strFileName,FileMode.Create)){fs.Write(m_byFile,0,m_byFile.Length);//写入回去这里也可能出现一瞬间的巧合}}elsem_fs.Close();//否则直接关闭文件占用enlistment.Done();}...其他实现}try{using(TransactionScopescope=newTransactionScope()){FileDelTestmyElistment=newFileDelTest("D:\123.test");Transaction.Current.EnlistVolatile(myElistment,EnlistmentOptions.None);thrownewException("test");//引发异常跳出using执行回滚scope.Complete();MessageBox.Show("main-OK");}}catch(System.Transactions.TransactionExceptionex){MessageBox.Show("main-"+ex.Message);}catch(Exceptionex){MessageBox.Show("main-"+ex.Message);}
不过还是会出问题的。。。出那一瞬间巧合的问题。。
那一瞬间的巧合是指什么?
解决方案:
引用30楼wjfwd2010的回复:
Quote: 引用29楼crystal_lz的回复:
Quote: 引用25楼wjfwd2010的回复:
Quote: 引用24楼starfd的回复:恩学习了,不过不能用IO操作。。。。那一瞬间的巧合是指什么?
刚才上面代码有问题不应该卸载commit函数里面那个是作为状态通知用的执行逻辑的代码要自己写如果执行了scope.Complete()就说明事物全部提交成功了所以如果中途有要中断的就不能让他执行到Complete直接让他跳出using执行rollbackpublicclassFileDelTest:IEnlistmentNotification{privateboolm_bDel;privateFileStreamm_fs;privatebyte[]m_byFile;//缓存数据privatestringm_strFileName;publicFileDelTest(stringstrFileName){m_strFileName=strFileName;m_fs=newFileStream(m_strFileName,FileMode.Open);m_byFile=newbyte[m_fs.Length];//先缓存数据m_fs.Read(m_byFile,0,m_byFile.Length);}publicvoidExecDel(){if(m_strFileName.IndexOf("456")!=-1){//假设第二个文件删除失败thrownewException("errortest");}m_fs.Close();//解除文件的占用File.Delete(m_strFileName);//但是这两句不在一个"事物"里面m_bDel=true;}publicvoidRollback(Enlistmentenlistment){if(m_bDel){//如果已经执行了commit了(有多个这样类的情况部分可能已经执行commit)using(FileStreamfs=newFileStream(m_strFileName,FileMode.Create)){fs.Write(m_byFile,0,m_byFile.Length);//写入回去这里也可能出现一瞬间的巧合}}elsem_fs.Close();//否则直接关闭文件占用enlistment.Done();}publicvoidCommit(Enlistmentenlistment){enlistment.Done();}...其他实现}try{using(TransactionScopescope=newTransactionScope()){FileDelTestmyElistment=newFileDelTest("D:\123.test");Transaction.Current.EnlistVolatile(myElistment,EnlistmentOptions.None);FileDelTestmyElistment_1=newFileDelTest("D:\456.test");Transaction.Current.EnlistVolatile(myElistment_1,EnlistmentOptions.None);myElistment.ExecDel();//执行删除myElistment_1.ExecDel();//执行删除//thrownewException("test");scope.Complete();MessageBox.Show("main-OK");}}catch(System.Transactions.TransactionExceptionex){MessageBox.Show("main-"+ex.Message);}catch(Exceptionex){MessageBox.Show("main-"+ex.Message);}
我指的一瞬间的巧合就是比如:应为这个并不是真正意义上的隔离而是模拟的隔离如上面我的代码我要删除两个文件那么我就先创建两个类把文件用FileStream占用并且把数据缓存起来然后挨个执行ExecDel()删除文件而上面的代码则第二个文件会删除失败则会跳出using则会执行rollback那么这个时候我就需要还原第一个文件但是由于已经被我删除了所以我需要创建一个一模一样的文件回去数据虽然我已经缓存起来了可以再写回去不过可能在我要写回去的一瞬间别人已经用FileStream创建了一个和我一样的文件在哪里导致我无法创建文件写数据回去这就是我说的一瞬间的巧合不顾没有这种巧合的纯在的话上面的代码应该就是要么两个我文件同时删除成功要么同时不成功不过这个都是模拟出来的。。
解决方案:
然而我发现做一个循环就可以了如果你只需要一对一的成功的话而不是全部记录和全部文件是一个整体的话try{数据库启动事物();if(受影响行数==1){File.Delete("文件");//如果出现异常回滚数据库提交事物();}}catch(Exceptionex){数据库回滚事物();MessageBox.Show(ex.Message);}
好吧其实我对贴出来的那个连接挺有兴趣的就看来一下也不坏。。。
解决方案:
引用31楼crystal_lz的回复:
Quote: 引用30楼wjfwd2010的回复:
Quote: 引用29楼crystal_lz的回复:
Quote: 引用25楼wjfwd2010的回复:
Quote: 引用24楼starfd的回复:恩学习了,不过不能用IO操作。。。。那一瞬间的巧合是指什么?
刚才上面代码有问题不应该卸载commit函数里面那个是作为状态通知用的执行逻辑的代码要自己写如果执行了scope.Complete()就说明事物全部提交成功了所以如果中途有要中断的就不能让他执行到Complete直接让他跳出using执行rollbackpublicclassFileDelTest:IEnlistmentNotification{privateboolm_bDel;privateFileStreamm_fs;privatebyte[]m_byFile;//缓存数据privatestringm_strFileName;publicFileDelTest(stringstrFileName){m_strFileName=strFileName;m_fs=newFileStream(m_strFileName,FileMode.Open);m_byFile=newbyte[m_fs.Length];//先缓存数据m_fs.Read(m_byFile,0,m_byFile.Length);}publicvoidExecDel(){if(m_strFileName.IndexOf("456")!=-1){//假设第二个文件删除失败thrownewException("errortest");}m_fs.Close();//解除文件的占用File.Delete(m_strFileName);//但是这两句不在一个"事物"里面m_bDel=true;}publicvoidRollback(Enlistmentenlistment){if(m_bDel){//如果已经执行了commit了(有多个这样类的情况部分可能已经执行commit)using(FileStreamfs=newFileStream(m_strFileName,FileMode.Create)){fs.Write(m_byFile,0,m_byFile.Length);//写入回去这里也可能出现一瞬间的巧合}}elsem_fs.Close();//否则直接关闭文件占用enlistment.Done();}publicvoidCommit(Enlistmentenlistment){enlistment.Done();}...其他实现}try{using(TransactionScopescope=newTransactionScope()){FileDelTestmyElistment=newFileDelTest("D:\123.test");Transaction.Current.EnlistVolatile(myElistment,EnlistmentOptions.None);FileDelTestmyElistment_1=newFileDelTest("D:\456.test");Transaction.Current.EnlistVolatile(myElistment_1,EnlistmentOptions.None);myElistment.ExecDel();//执行删除myElistment_1.ExecDel();//执行删除//thrownewException("test");scope.Complete();MessageBox.Show("main-OK");}}catch(System.Transactions.TransactionExceptionex){MessageBox.Show("main-"+ex.Message);}catch(Exceptionex){MessageBox.Show("main-"+ex.Message);}
我指的一瞬间的巧合就是比如:应为这个并不是真正意义上的隔离而是模拟的隔离如上面我的代码我要删除两个文件那么我就先创建两个类把文件用FileStream占用并且把数据缓存起来然后挨个执行ExecDel()删除文件而上面的代码则第二个文件会删除失败则会跳出using则会执行rollback那么这个时候我就需要还原第一个文件但是由于已经被我删除了所以我需要创建一个一模一样的文件回去数据虽然我已经缓存起来了可以再写回去不过可能在我要写回去的一瞬间别人已经用FileStream创建了一个和我一样的文件在哪里导致我无法创建文件写数据回去这就是我说的一瞬间的巧合不顾没有这种巧合的纯在的话上面的代码应该就是要么两个我文件同时删除成功要么同时不成功不过这个都是模拟出来的。。
逻辑漏洞肯定还有很多,但是不牵扯到本问题了,但是思路已经很好了。至少比直接删除强了。感谢回答。
解决方案:
引用32楼crystal_lz的回复:
然而我发现做一个循环就可以了如果你只需要一对一的成功的话而不是全部记录和全部文件是一个整体的话try{数据库启动事物();if(受影响行数==1){File.Delete("文件");//如果出现异常回滚数据库提交事物();}}catch(Exceptionex){数据库回滚事物();MessageBox.Show(ex.Message);}好吧其实我对贴出来的那个连接挺有兴趣的就看来一下也不坏。。。
你这样不行吧,如果删除了文件陈宫,数据库提交事务这里还是可能出异常的。数据库提交事物();出了异常File.Delete("文件");/这里是不会回滚的。
解决方案:
数据库提交事物();出了异常File.Delete("文件");/这里是不会回滚的。好吧这个就不知道了应为平时写代码对数据库要求都不怎么高基本上都用不到事物没有遇到过数据库执行事物提交的时候出异常的。。。
解决方案:
数据没了文件还在文件没了数据还在肯定选第1个啊第二个相当于你数据丢失了,对你的业务是有影响的,而第一个相当于你文件是废的,但是你再也不会用到这个文件,不影响你应用的功能最多造成硬盘空间的浪费你可以凌晨写个定时程序跑跑看哪些属于数据没了文件还在的然后删除这些垃圾文件不久行了
解决方案:
做软删除,然后定期清理,不知可否?
解决方案:
引用2楼wjfwd2010的回复:
Quote: 引用1楼linux_010的回复:
挂接主外键关系,根据主键删除跟我问的问题没关系吧我是说你是先删除数据还是先删除文件呢?如果先删除文件,删数据的时候出异常,那么你文件就没了,如果你先删数据,删文件的时候你数据就没了。。。。
如果我让你只删数据,不删图片呢?如果我让你3个月以后再删除图片呢?
解决方案:
引用37楼a386574648的回复:
做软删除,然后定期清理,不知可否?
是的,完全可以在删除数据之前先记录一个“清理计划”,里边写了“如果某个数据查询不到,则删除某个图片”。有了这个计划,那么就可以定期清理了。
解决方案:
其实楼主,最关键的是,如何真正、保质保量的删除一张图片!数据库好说,回滚或者删除前把路径记录到一个temp表里,顺序:删除路径--->删除图片,IF删文件成功THEN删除temp表里的记录ELSE将temp里的路径写回去,然后删除temp里的路径关键是删除图片,要不能删除,那么可能就不能重命名,也不能移动,现在删不掉,将来也可能删不掉,这样,定时清理也可能做不到。有些安全软件,有粉碎文件功能,其实多数情况,手工删不掉的,也粉碎不了所以建议楼主把方向转到如何真正删除掉一个文件
解决方案:
把图片直接存数据库了
解决方案:
图片可被多次使用,所以同一图片路径可能在数据库中保存多次所以删除记录时删除文件的做法是不可取的
解决方案:
引用39楼sp1234的回复:
Quote: 引用37楼a386574648的回复:
做软删除,然后定期清理,不知可否?是的,完全可以在删除数据之前先记录一个“清理计划”,里边写了“如果某个数据查询不到,则删除某个图片”。有了这个计划,那么就可以定期清理了。
这不就是我在15楼说的么,只不过你帮我定义了一个名字叫清理计划。感谢。
解决方案:
对图片判了死刑,没有必要立即执行,可以缓期1个月执行,说不定这个图片表现良好,无罪释放呢。
解决方案:
诶呀好吧,我错了,我说图片只是一个例子,如果是其他文件呢?
解决方案:
先删数据再删文件吧或者有一个BAK表来保存删除的数据因为不排除客户需求并不要求文件即时删除可能会几个月后。。。
解决方案:
圖片檔轉成2進位,存到DB欄位裡面,這樣就可以同步一起刪除了。
解决方案:
倾向是数据库事务,事务逻辑是先文件再数据……先不管会不会发生所谓的意外,从执行完整度和“绝大多数安全”的角度,推荐……如果不具备事务条件,或不想用事务,个人认为还是删文件再删数据……个人感觉文件是对象,数据是变量内容,遍历调取对象的文件名不如遍历变量内容效率……另外……如果是记录文件那里也是变量,(比如记录的文件名),个人觉得也是先删文件,如果数据先删除了,文件却还保留,那岂不是浪费了空间?如果文件删除数据没能删除,充其量也只是报个“找不到文件”的错误。我更支持后者。