多线程操纵数据库 希望大家给一些意见
想用多线程来控制数据库的操作,但思路不是很清析,不知道多线程是否会提高效率,在网上找例子又几乎没有。针对下面几个问题,希望大家给出意见,并希望大家给出更好的思路。
多线程操纵数据库有没有必要?
我是否应该有四个线程就够了,一个SELECT,一个DROP,一个UPDATE,一个INSERT?或者更多个,当进程过多时我是否需要控制数量。
连接用完是关闭还是一直打开?
方法用不用加锁?
还应该注意什么?
希望大家多给宝贵意见
我用的是.NET2.0 SQL2000/2005
[解决办法]
有必要?
[解决办法]
我个人认为:
1.有必要用多线程,毕竟会提高程序运行效率,特别是在数据较大时,用线程不会让用户感觉到程序正在处理数据,而不能响应用户的操作.
2.我认为有一个线程就够了,如果线程过多,那数据的一至性和并发处理将会是一大难点.
3.连接一直开着,至到所有的程序都不再用连接时再关闭.如果是用完就关闭,那样将会给程序的性能带来比较大的影响.
4.应该加锁,那样出现并发的机率又降低了.
另外,我觉得应多用事务和存储过程,事务具有(完整性,一至性,持久性)这都是优点,有优点为什么我们不用.存储过程是数据库预编译好了的,用起来速度将会比用sql语句好得多.由其是在有数据计算时.
[解决办法]
如果这四个东西互相不会LOCK的话 而且你的数据库够强的话 应该会提高效率吧
[解决办法]
个人觉得:
1.如果只是查询,如果你的程序并发访问量很大,我觉得有必要用多线程,但如果通过现有的一些优化的方法可以解决问题,建议不用多线程,毕竟并发访问需要控制的东西很多,一个小失误都会成为瓶颈,反而得不偿失。
2.如果是事务要求严格的应用,不建议多线程,大并发量的处理将浪费过多的服务器资源,而程序如果这方面做的不好,所有的连接都会出于等待状态,占着茅坑不拉屎,没意义,况且现在都有连接池技术,控制好就可以,没必要自己重新造轮子,搞好了就什么都不说了,搞不好了别想奥运门票事件就不好了。
3.对于DML不建议多线程,死锁问题,并发的时候很难搞的很难搞。
4.说下对3楼的存储过程想法的不同见解,如果你的程序不大,创建的视图,索引,存储过程不多,无所谓,但你的程序很大,创建了N多以上说的预编译的什么的东西,如果你公司负责数据维护的人比较忠诚还好,一旦跳槽现象很频繁,接手交接问题,以及对新手培训的费用将大大增加,而且连带问题多多。所以我的建议是:能SQL语句搞定的,尽量SQL语句搞。
[解决办法]
要注意一下几点
1.多线程访问数据库有必要
2多线程访问数据库线程的数量要受到控制
3每个线程都可以做SELECT,DROP,UPDATE,INSERT
4 数据库数据写入要用事务
5 数据库数据写入表的顺序要保持一致
完成这样要求的具体代码是:
using System;using Server;using PublicControl.Run;using PublicControl.DataBas;using System.Data;using System.Data.SqlClient;namespace Server.RUN{ /// <summary> /// RunApp 服务器执行的虚拟类 /// </summary> public abstract class RunApp { /// <summary> /// 使用本服务的用户 /// </summary> protected OnlineUser onlineUser=new OnlineUser(); /// <summary> /// 运行参数 /// </summary> protected RunParam runParam; /// <summary> /// 共享服务提供类 /// </summary> protected PublicServer publicServer; /// <summary> /// 数据库应用对象 /// </summary> protected DataBasAPP dataBasAPP; /// <summary> /// 是否继续运行 /// </summary> protected bool fContinueRUN=true; /// <summary> /// 挑选需要处理的数据 /// </summary> protected virtual void SecurityCheck() { OnlineUserCache temp=(OnlineUserCache)this.publicServer[onlineUser.GetType().FullName]; OnlineUser user=temp.GetData(runParam.UserID,null); if(user==null) { runParam.Error=true; runParam.ErrorInfo="您没有登陆系统请登陆后在做操作."; return; } if(user.SecurityPassword!=runParam.SecurityCheck) { runParam.Error=true; runParam.ErrorInfo="信任关系校验失败,请重新登陆.\n很有可能是您又在其它地方登陆了."; return; } onlineUser=user; user.UserWorkTime=DateTime.Now; } /// <summary> /// 挑选需要处理的数据 /// </summary> protected abstract void SelectDataList(); /// <summary> /// 开始预处理 /// </summary> protected abstract void BeginRUNList(); /// <summary> /// 处理结束收尾. /// </summary> protected abstract void EndRUNList(); /// <summary> /// 更新数据库 /// </summary> protected abstract void UpDataList(); /// <summary> /// 是否继续运行 /// </summary> protected bool ContinueRUN { get { return fContinueRUN; } set { fContinueRUN=value; } } /// <summary> /// 空构造 /// </summary> public RunApp(){} /// <summary> /// 执行 /// </summary> /// <param name="RunParam">执行参数</param> /// <param name="PublicServer">共享数据服务</param> /// <param name="DataBasAPP">应用数据库</param> public void Run(RunParam RunParam,PublicServer PublicServer,DataBasAPP DataBasAPP) { runParam=RunParam; publicServer=PublicServer; dataBasAPP=DataBasAPP; try { runParam.ServerDequeueQueueTime=DateTime.Now; if(fContinueRUN && !runParam.Error) { SecurityCheck(); BeginRUNList(); } runParam.ServerPretreatEndTime=DateTime.Now; if(fContinueRUN && !runParam.Error) { dataBasAPP.OpenDataBas(); SelectDataList(); dataBasAPP.CloseDataBas(); } runParam.ServerSelectDataEndTime=DateTime.Now; if(fContinueRUN && !runParam.Error) { dataBasAPP.OpenDataBas(); SqlTransaction myTransa=(SqlTransaction)dataBasAPP.BeginTransaction(); try { UpDataList(); myTransa.Commit(); } catch (Exception e) { myTransa.Rollback(); throw new Exception(this.GetType().FullName + ":" + e.Message + "\r\n" + e.StackTrace + "\r\n" + e.TargetSite.Name); } finally { dataBasAPP.CloseDataBas(); } } runParam.ServerUpDateEndTime=DateTime.Now; if(fContinueRUN && !runParam.Error) { //dataBasAPP.OpenDataBas(); EndRUNList(); //dataBasAPP.CloseDataBas(); } runParam.ServerSendStartTime=DateTime.Now; } catch (Exception e) { dataBasAPP.CloseDataBas(); runParam.Error=true; runParam.ErrorInfo=this.GetType().FullName + ":" + e.Message + "\r\n" + e.StackTrace + "\r\n" + e.TargetSite.Name; } } }}
[解决办法]
lz用多线程有什么意义呢?为什么要用多线程访问数据库?如果并发得太多,数据库如果性能不行,是会适得其反啊