程序高速从TCP接收数据后insert存入SQL Server数据库,导致其窗口不可见(如果当前窗口是其他程序)或不可控(虽可见但鼠标无效窗口象死了一样),怎么办?
自己能想到的办法主要是优化运行的程序,比如把接收数据处理里的dim放到整个form上面,用存储程序存数据(insert写进存储程序) 。但是还是不能解决问题。
自己能想到的办法主要是优化运行的程序,比如把接收数据处理里的dim放到整个form上面,用存储程序存数据(insert写进存储程序) 。但是还是不能解决问题。
主要问题在于,从TCP读写数据和向数据库读写数据与你的程序位于同一线程中,如果处在读写数据的循环里,就没有机会去处理窗口消息,也就是假死的产生。
解决方法可以是在读写数据的循环里调用DoEvents,但是会比较严重的影响性能;另一个方法就是向其他语言寻找多线程的支持,或者单独编写另一个程序专门用于读写数据,使用进程间通信技术进行同步。
不过单单用一个DoEvents还不够,程序虽然可以由用户控制,但是CPU的占用率还是会居高不下!最好使用:Private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)For i = 10 ^ 6
Debug.Print i
Sleep 1
DoEvents
Next i
DoEvents
从98%降到0%
不太懂DoEvent。我在每次调用存储过程之后写DoEvents,但是无效,还是假死
查了一下,DoEvents的用途是“转让控制权,以便让操作系统处理其它的事件”,也就是避免整个电脑的假死而并不能避免该程序的假死?还是把控制权从某个Sub或函数让出,避免该程序窗口的假死?
1)如果用多进程,是一个进程用winsock接收另一个用存储过程存储吗?
2)VB6可以用多进程吗?怎么用?
3)DoEvents在这个问题上能起什么作用?怎么用?
如能示意性地写一下VB6的代码不胜感激。
这里加Sleep 1 运行到何年何月去了啊
一个线程可以理解为一条单一的代码执行路径,前面的代码没有执行完,后面的代码就不会被执行。
如果用多线程,就是一个线程管用户界面,一个线程管数据读写,当然可以再细化为一个线程winsock一个线程搞数据库。
基本上可以认为VB6不能用多线程。
如果程序假死的瓶颈在于网络数据交换或者执行存储过程而非程序本身的循环,doevents在这里起不到什么作用。你应该做的是考虑使用多个单独进程来执行不同任务。举例来说,写程序netaccess.exe执行网络数据交换;dbaccess.exe执行数据库存储过程,通过命令行参数和额外的文件在这些程序间交换数据,或者通过一些进程间通信技术来在它们之间进行通信。
也许可以这样:程序A从winsock里读数据,程序B向sqlserve里存数据,中间我只会用文本文件交换数据。但问题是,A程序存到文本文件一定比存到sqlserver快吗?否则A还是会假死啊。
http://topic.csdn.net/t/20061205/16/5208363.html
多线程不会,而且似乎也不好处理,因为读必须用winsock的DataArrival事件。试了一下19楼lyc59888兄的timer办法,DataArrival事件把读到的数据转到Byte数组(winsock最大一次读取量的10倍,以避免处理不完)中,用timer1去翻译数组并存入sqlserver(我觉得把翻译和存储分到2个timer里可能没有益处)。
试验了一下,timer1不启动一切良好(大部分情况下DataArrival的buffer都没有满,说明winsock得到的cpu足够),timer1一旦启动则开始半假死(按停止按钮十几秒后起作用),此时DataArrival的buffer经常满(说明cpu已经开始不太够),比原来有改善,但是还是不行。看来需要前面sworddx兄和alifriend兄所说的多线程多进程的办法或myjian说的调用ActiveX的方法,不幸我根本不会。哪位“会者不难”的兄弟能否帮我写一下代码搞定此问题?100分+100人民币?
注:界面和处理的代码都是现成的,低速率调适正常,只需要解决高速率的问题。
每秒DataArrival事件的次数多、还是每次收到的数据量大?
如果DataArrival消息太多,肯定无法将界面操作排入消息队列了。如果可以的话,加大缓冲区大小,设法让发送端将多次的小数据发送合并成一次大数据发送。
还有(这已经是第几遍说了)加上反馈机制,接收端处理了数据包后反馈给发送端,然后发送端才运行发送下个数据包,这才是从根本上杜绝超量发送引发接受端阻塞问题的方法。
只延时1毫秒,循环1000次才一秒,况且我看楼主的软件使用对象对这个程序的处理效率估计也不会有太多要求
再说了,我从来都是用Sleep+DoEvents,也从来没试过电脑没响应,如果用了还没响应的话,估计也是其它代码有问题至于效率,现在的电脑内存都是以GB来计算了,CPU单核的都达到3GB+了,普通使用软件的人也不会打开“任务管理器”去查看程序的内存占用量!
1)每个数据包2000个byte。需要处理为30x30个integer数组元素,然后再存入sqlserver(30条)。
2)所谓高速,我试验的结果是,1秒1个数据包没问题(1次DataArrival),再快就要假死。而实际可能每秒10个DataArrival。
3)winsock的缓存好像是固定8192吧?不知道怎么加大。
4)合并小数据当然好,问题是发数据包的是现有设备,无法改其软件。
5)反馈机制同样好,通信里面也都是这么做,但问题同上没有办法。
sleep是哪里的函数?vb6里没有啊。
处理效率其实要求很高,每秒10个数据包源源不断而来(可能持续几个小时),而程序处理每秒1个以上就要假死。
在调用存储过程的语句后加了DoEvents(不知是不是这么加?)
异步执行的事还望明示.调用存储过程算异步吗?
我是用1个存储过程插入30条数据(里面有30条insert命令).
我只知道用union all可以一条insert插入30条数据,但是好像也并不比30条insert快.
这里我对类似问题有个方案:http://topic.csdn.net/u/20080622/02/ea5452eb-3566-4e11-8b27-2b4b796d22d3.html
1)我都是用command。commandtype根据直接还是存储过程而定。
2)您30楼的提案已经试了,速度高后写文本文件也假死了(更不要说处理和存入sqlserver)。我想硬盘操作总比内存慢,所以仅仅是把byte翻译为string然后写入文本文件就足以假死(还没有作其它处理例如二进制byte转double浮点和int整数等)。
3)您的http://topic.csdn.net/u/20080622/02/ea5452eb-3566-4e11-8b27-2b4b796d22d3.html也学习过了(多谢您多处帮忙),但我的问题是发端是人家的设备,别人编的接收程序据说可以正常接收处理存储,而我的则假死不行,所以还是只能从自己这里找原因。
2.不要每来一个请求就执行一次insert,对于SQLServer完全可以缓存到500~1000条再批次执行(多条insert之间使用分号分隔即可)
3.ADO执行异步执行,所以可以考虑采用异步执行另外,要说的是对于高速运行的网络IO放在UI同一线程当中,很难免除相应的问题,个人觉得有一个可行的办法就是写成ActiveX EXE,UI以外的内部放到一个Modal当中,由Form启动以后再创建出实例,从而使种它以后台线程方式来运行。从中导出一些Event用于与UI(Form)进行一些信息交换
客户端只负责把数据传给中间层的COM+服务器,然后由中间层完成数据库的UPDATE,INSERT,SELECT等操作
这样做即能保证数据的完整性,以免发生以外造成错误数据(因为COM+有事务处理机制)
还能为客户端分担一部分负担
程序假死没关系,只要生成文件没有丢包就可以了。
在我的方案中,反馈机制只是为了防止过量传输导致丢包的问题,既然其它程序可以正常接收,就不需要该机制了。你只要实现方案中的接受端部分,接收程序直接将收到的包按byte类型存入文件,通常硬盘操作总是快于TCP传输的,所以用文件没问题。
你所谓的“把byte翻译为string”功能应该归在数据处理程序中,尽量保证接收程序的速度。界面设计上,接收程序隐藏不可见,也就不存在什么假死问题了;
数据处理程序有画面,因为是定时扫描目录的,所以在更新数据库时可以将定时器暂停,这样你只要处理好数据更新部分,界面不存在假死问题;
两者关联上,数据处理程序通过 Shell 函数启动接收程序;需要关闭时也可创建一个标记文件让接收程序定时扫描,当然也可以用其它方式关闭接收程序。
在TCP/IP协议当中,如果对端没有接收下来数据又如何认识已经发送成功,可以进行后续报文的发送?为什么发送异常不加以处理?我从来没有听说过这样存在的问题叫做是“合理”。在网络传输当中存在这样的问题,难道单依赖于接收端就可以单方面把问题解决掉?那还有谁敢用?一个TCP包,随便中间缺少一个字节,那这个报文还能正常解析?难道中间传输的全是无关紧要的数据?
大家好,我用的vb程序运行起来也很占cpu,有时界面也死掉,但程序是运行的(通过串口,在执行发送数据),当数据发送完,界面才可以操作。上面这位朋友的代码要怎么使用?直接全部cope到程序里吗?在下刚学vb,边用边学
“放到线程当中”,不会啊!如何对放到线程中呢?呵呵,难了不会,会了不难吧现在的问题就是程序通过串口发数据时,太占cpu,我在发送程序中加sleep好吗? Sleep和DoEvents要配合使用吗?我以前一直单独使用sleep啊
com+不懂。可以用vb6?说详细点?
关于一些没有任何实质性意义的话题,个人不想与你再争吵,你有权力去坚持你个人的观点。只是不希望一些所谓的新人把这些当成一个“典范”。To All:
我个人并不是什么权威,所以也不希望别人生般硬套去接受或者不接受。只是通过一些讨论,希望大家得到启发,从而通过经验积累,包括试验,以及一些相关的权威性的资料(书上说的不一定都是正确的,加上自己的思考是非常必要的),特别如MSDN以及一些相当经典的材料进行分析。不管是老板,还是客户,甚至是你的上级,在技术领域当中并不能代表权威,但是你需要有足够的理由让他们了解、理解并且接受你的方式或方法或者对于问题的分析。当然讨论的目的并不是说让谁违背着上级、老板或者客户地意愿去做事。只是出于尽可能减少或减轻成本,以及维护量,达到更高的生产效率和系统稳定性。就上面我说的这种情况,如果确实碰到,那么可以通过分析和检验报文的完整性来进行处理,因为人有时候反抗不了就得学会遵从。
个例性的偶然性的问题并不具代表性,希望以后跟你讨论问题的时候,举出来的例子是具有代表性的。不管是平常的讨论,还是今后工作中,特别是对待下属的时候,举证的可信服度是非常必要的,否则如果没有什么说服力的话,对个人对大家都不存在好处。
我对winsock的机制不太了解,我理解应该是DataArrival结束后winsock会自动发响应给另一端。结果由于我的DataArrival处理过慢,反馈的响应也就过慢,导致发端因等候响应而数据发不出来而失败。
用通信的术语讲,tcp的send window不知是多大?window固定为1还是可调?
你试试在调用GetData后直接抛弃数据不做任何处理,这样是否能响应最高速率的传输。
如果还断掉,在找不到设置传输速率的情况下,只能考虑换控件了。
如果不会断掉,那么考虑将几次GetData()得到的数据缓存起来,积累到一定量后再外送。还有最好用高精度计数器统计一下,各部分的耗时多少,便于针对瓶颈优化。
直接抛弃没有问题。而且我做了一个10倍于8192的缓冲数组,把收到的数据拷贝到缓冲数组中,也没有问题。
没有问题的具体含义是:数据包长2000,DataArrival里的BytesTotal有2000的也有4000的,但是没有更多,也就是不会发生比较复杂的粘连。积累几次GetData再处理是个好主意,起码对于我这样没有更高级手段(例如多线程)的人来说是这样的,只是这样需要太多的变量(一次就需要30x30,10次岂不是30x30x10,近万个变量不仅骇人听闻,而且就怕处理起来还是超时)。我有时间试一下吧。高精度计数器我不懂。瓶颈呢,以前以为主要是写sqlserver,后来发现光是转换数据也不够时间,所以瓶颈应该既包括转换数据也包括sqlserver。具体点说呢,转换数据用到了CopyMemory,sqlserver用了union,CopyMemory听说不是很快,union倒是1条顶30条insert。另外,老兄的写硬盘文件的方法,最开始我自己也曾想过,但是一来这么高速率怕很难实时处理,二来说实话觉得用文件而不是更高级的办法看上去有点土(我自己土,没有得罪老兄的意思)。
sqlserver方面,insert估计慢也慢不到哪儿去,而查询就难说了30x200x500=三百万条记录,select起来怎么也是10秒级的,所以到那时候我的绘图程序还会出问题,那将是我的下一个大难题。由于不会在程序之间传递变量,马上就又想到了tiger_zhao兄说的硬盘文件的办法。
唉,走一步说一步吧。
1)DataArrival收到数据后,调用线程A翻译并存入sqlserver。
2)DataArrival收到数据后,调用线程A翻译,调用线程B存sqlserver。两个方案,1)比较简单,2)还要协调A和B(例如设翻译处理标志等)。问题是:
多线程可以避免界面假死?
多线程可以抢占更多的cpu?
不管几个线程,如果处理速度还是跟不上接受速度,缓存再大也是要满的(高速连续几个小时),最后岂不是tcp还是要因阻塞而断掉?
CopyMemory用于把收到的二进制byte转换为double浮点数,好象VB里没有别的更好的办法。字符串当然不用,integer整数也没有用。
On Error Resume Next
Debug.Print bytesTotal
Winsock1.GetData DBdata(), vbByte + vbArrayDBid = DBdata(2) '第2个byte表示消息类型
If DBid = 4 Then '4代表数据
For ccc = 0 To 29 '每个数据包30个数据点,每个数据点有5+30个integer字段
bpdp = 88 'bytes per data package
DBcc(ccc) = CInt("&H" & DBdataStr(7 + ccc * bpdp) & DBdataStr(6 + ccc * bpdp) & DBdataStr(5 + ccc * bpdp) & DBdataStr(4 + ccc * bpdp))
DBsf(1, ccc) = CInt("&H" & DBdataStr(11 + ccc * bpdp) & DBdataStr(10 + ccc * bpdp) & DBdataStr(9 + ccc * bpdp) & DBdataStr(8 + ccc * bpdp))
DBsf(2, ccc) = CInt("&H" & DBdataStr(15 + ccc * bpdp) & DBdataStr(14 + ccc * bpdp) & DBdataStr(13 + ccc * bpdp) & DBdataStr(12 + ccc * bpdp))
DBsf(3, ccc) = CInt("&H" & DBdataStr(19 + ccc * bpdp) & DBdataStr(18 + ccc * bpdp) & DBdataStr(17 + ccc * bpdp) & DBdataStr(16 + ccc * bpdp))
DBsf(4, ccc) = CInt("&H" & DBdataStr(23 + ccc * bpdp) & DBdataStr(22 + ccc * bpdp)) '& DBdataStr(21 + ccc * bpdp) & DBdataStr(20 + ccc * bpdp))
For hhh = 0 To 29 '每个数据点30个字段
DBchData(hhh + 1, ccc) = CInt("&H" & DBdataStr(23 + ccc * bpdp + hhh * 2) & DBdataStr(22 + ccc * bpdp + hhh * 2))
Next hhh
Next ccc
With cmd
.CommandText = "dbpro_data_in" '该存储过程将30条数据insert进sqlserver
.CommandType = adCmdStoredProc
.CommandTimeout = 0
For i = 0 To 19
ii = Right("0" & Trim(Str(i + 1)), 2)
.Parameters("@cc" & ii) = DBcc(i)
.Parameters("@sf" & ii & "01") = DBsf(1, i)
.Parameters("@sf" & ii & "02") = DBsf(2, i)
.Parameters("@sf" & ii & "03") = DBsf(3, i)
.Parameters("@sf" & ii & "04") = DBsf(4, i)
For j = 1 To 40
jj = Right("0" & Trim(Str(j)), 2)
.Parameters("@d" & ii & jj) = DBchData(j, i)
Next j
Next i
.Execute
DoEvents
End With
End If
End Sub注:CopyMemory这里没有,另一个一次性的消息里用(1小时1次所以速度无所谓),这里都是2字节或4字节的integer
总之很简单,按规定一段一段截二进制byte并转换为int(低位放前面高位放后面),然后调用存储过程。原来是一条insert一次,后来怕慢就30条insert一次(存储过程里用了insert select union)。
是啊,这代码不仅乱而且不好。开始是想用16进制显示收到的代码,所以
dim DBb as long
DBb = DBdata(i)
DBdataStr(i)=IIf(Len(CStr(Hex(DBb))) = 1, "0", "") & CStr(Hex(DBb))后来发现速度不行,也没有去再改。是不是可以用CopyMemory直接翻译integer要快些?
你要做的不过是把4个Byte转为long
而如果使用CopyMemory的话,你可以一次性把N*4个Byte复制到N个Long当中。
数据库如何异步?
多建command相当于多进程?
看你似乎先将 DBData 转换为 String 类型的 DBdataStr(),再逐个转化为 Integer 值,完全没有必要;定义好正确的 Type 后用 CopyMemory 就可以解决的。
高精度计时器如下
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Longprivate m_Frequency as currency
private m_aExpend(1 to 2) as currency
private sub form_load()
QueryPerformanceFrequency curFrequency '这是个定值,只需要初始化一次
end subprivate sub form_unload(...)
dim i as long
for i=1 to 2
Debug.Print "代码段" & i & "总耗时 " & FormatNumber(m_aExpend(i)/m_Frequency, 7) & " 秒"
next
end subprivate sub Winsock1_DataArrival(...)
dim curStart as currency, curFinish as currency
'代码段1
QueryPerformanceCounter curStart
...
QueryPerformanceCounter curFinish
m_aExpend(1) = m_aExpend(1) + (curFinish-curStart)
'代码段2
QueryPerformanceCounter curStart
...
QueryPerformanceCounter curFinish
m_aExpend(2) = m_aExpend(2) + (curFinish-curStart)
end sub
1)封掉with cmd里所有命令,正常。
2)执行with cmd里的所有命令,不正常。
3)封掉后面的存储过程调用,不正常。(在with cmd里仅封掉.execute)看来问题在于对存储过程变量赋值和调用存储,而这两个显然缺一不可,而且我也想不出好的解决办法。
我也试了直接用command单条存储,同样不行。
能想到的优化已经作了:2条CopyMemory替代了30+4条转换命令(不再事先转换为string)。
多线程我觉得并不一定能解决问题,异步数据存储也不行,因为再多的线程和异步如果不能及时处理数据,都会产生接收端的数据淤积,并最终导致发送方tcp窗口减到最小而导致数据传送失败。
异步还有一个问题,就是另外还有程序会读取sqlserver而实时显示数据,异步时延过大会使实时显示无法进行。
如果存储过程当中并没有太过复杂的处理,仅仅只是一个Insert的话,个人并不建议使用存储过程。对端之所以断掉,估计应该是发送超时。对于异步处理,跟显示数据本身并没有任何关联性的影响,之所以会有影响,是因为你使用的数据库锁,或者说连接上面的隔离级别不对。比如发送端,如果你使用的是with (nolock)或者with (readpast)那么就不会有影响。
1)使用存储过程是听说比较快。不过也可以试一下直接用insert select union all。
2)异步的事我始终没有搞清楚。存储过程是异步吗?用DoEvents是异步吗?
3)显示的问题和异步的关系在于,如果异步存储的是10分钟以前的数据(由于处理速度不够),那么我们不可能显示最近10分钟的数据,所以不能做到真的实时显示。
4)我想大概可以用超大数组,这样把所有收到的数据放入数组,起码不会丢数据。而且已经试验过存数组的速度是没有问题的。据说数据不能超过long的范围也就是2,147,483,647,这对于我估计的2百万最大数据条数应该够了,只是2M x 40个integer应可能超过计算机2G内存(数组会先存入内存?),超过后操作系统会用硬盘替代?效率可能也不行。
2) 存储过程并不是异步,存储过程只是把一大批的频繁使用的命令集中在一起,并且由于存储过程在数据库当中会进行Compile,所以会有一定的性能提升,但并不是建议在这些insert之类的简单命令的基础上的,比如使用游标进行批量数据的处理等等;DoEvents也不是异步,DoEvents只是为了使得当前线程能够响应Windows消息,从而插入一些临时的消息处理,而使得一些基于消息的动作得到处理,包括窗口上面的刷新,以及平常的鼠标拖动等等,如果懂得中断概念的话,那么这个就属于“中断”,如果有消息投到消息队列当中的话.
3) 数据没有入库,那明显无法进行显示,除非直接投到显示窗口当中,而不是数据库中转,但是这个可能就不再符合设计,甚至只能是想想罢了
4) 使用内存进行缓存,那只是暂时的,通常用于处理那些,间歇性集中流量的数据,比如某一分钟可能突然要传好几百条数据,而后可能会歇个两三分钟再来一批,对于一直连续不断送过来的数据,通过一定的时间,如果不能及时处理,只能使得缓存越来越大,最终整个系统由于内存的过度消耗而越加缓慢,越加堆集,而陷入死循环,好一点的情况是对端中断连接,坏一点的情况是整个系统挂起不再工作。
我们在考虑这些问题的时候,需要集中在:
a. CPU的处理能力是否已经完全达到利用
b. 业务流程各个环节还能不能进行进一步的性能改善,包括流程的改善以及编码效率提升
1)我只知道insert union all可以一次插入多条数据。而如果一次一条速度当然就慢了。
2)事务的好处在这里例子里没看到,我不需要回滚,反而觉得事务会降低存储速度。
3)还是不知道异步具体该怎么做。
4)我如果能把所有收到的数据都放入物理内存(假设2G够用),那么系统也会缓慢吗?
5)提高CPU利用率有什么办法?多线程可以吗?
6)我的业务流程很简单,收到数据>翻译>入库,好像看不到余地了(除了全部存入数组然后慢慢入库)。
cmd.CommandText = "insert into rdata" & _
"select 0," & DBcc(0) & "," & DBsf(1, 0) & "," & DBsf(2, 0) & "," & DBsf(3, 0) & "," & DBsf(4, 0) & "," & DBchData(1, 0) & "," & DBchData(2, 0) & "," & DBchData(3, 0) & "," & DBchData(4, 0) & "," & DBchData(5, 0) & "," & DBchData(6, 0) & "," & DBchData(7, 0) & "," & DBchData(8, 0) & "," & DBchData(9, 0) & "," & DBchData(10, 0) & "," & DBchData(11, 0) & "," & DBchData(12, 0) & "," & DBchData(13, 0) & "," & DBchData(14, 0) & "," & DBchData(15, 0) & "," & DBchData(16, 0) & "," & DBchData(17, 0) & "," & DBchData(18, 0) & "," & DBchData(19, 0) & "," & DBchData(20, 0) & "," & DBchData(21, 0) & "," & DBchData(22, 0) & "," & DBchData(23, 0) & "," & DBchData(24, 0) & "," & DBchData(25, 0) & "," & DBchData(26, 0) & "," & DBchData(27, 0) & "," & DBchData(28, 0) & "," & DBchData(29, 0) & "," & DBchData(30, 0)要是写30条岂不是长死了,所以就根本没有想把DBchData改名为Dch之类的办法。看来还是只能用存储程序把900个变量穿过去然后在存储程序里写insert union all。但是对900个变量赋值这部分时间又受不了。好像除了大内存就没路了。
1) insert ...data1...;insert ...data2...;insert ...data3...;insert ...datan...,这样就可以替代union all,一般来讲一次可以提交500~1000笔,从而减少与数据库的交互(网络)次数,以提升效率
2) 事务是肯定存在的,只要对数据进行过修改(包括新增和删除)。只是如果你没有使用显式事务,则由系统来执行事务策略,即隐式事务。
3) 实际上如果只是insert,并且数据库当中的索引使用合理的话,那么基本上不需要异步也不需要多少时间,如果你要进行异步执行,那么就首先需要建立数据环境池(多个连接和Command组成,当其中一些被占用的时候,其他空闲的可以顶上来被使用,使用数组就可以完成),当然每次都申请新的是可以,但是频繁创建和销毁对象也是需要消耗时间的.ADODB.Command.Execute的第三个参数,可以带上adAsyncExecute,即为异步执行,但是需要注意ADODB.Command的一些相关事件需要进行处理
4) 2G内存并不算多,即使你有超过2G以上的内存,试问一下,VB6能用到多少内存?超不过2G,再说能缓存的数据量也是有限的,并且就象你把手头上忙不完的工作堆积下来,没啥区别
5) 提升CPU的利用率,并不一定要使用多线程,除非你的机器是多CPU(包括多核心),我的意思是先要看一下你当前的CPU压力能达到什么程度,如果满负荷(单核心当中,比如你的CPU是双核的,那么只需要占用到总的50%就算),那么你操作数据库是否需要使用异步并不太重要。
6) 你所给出的业务流程只是一个大概的,每一个分步当中还包含很多细节,比如说通过内存占用来达到性能提升,比如说将数据进行短时间缓存然后一次性提交等等