为了提高数据及时性,需要每次提交都CHECKPOINT吗?

仙侣步惊云 2015-03-25 11:15:07
以前做一个CS系统,有很多终端同时更新数据,例如有50个终端同时更新大量财务数据,每笔数据都是很小的,客户端提交到数据库时,会发现出现数据莫名丢失的现象,例如客户端明明在一个小时内共计更新了6000条记录,结果从客户端只能查询到5992条记录,另外8条记录却不见了,但如果全部客户端全部退出登录,则可以查询到全部记录,真要命!
后来才知道,客户端数据提交时只是保存在数据库服务器的缓存中,并不会立即更新,只会在系统设置的一个固定时间片只(例如30秒)提交给数据库磁盘文件内,而从客户端查询的数据,只是从数据库磁盘文件中取出数据查询,并不会把缓存中的记录算在内,所以,一边在大量更新提交数据库,一边要及时查询了解更新情况,如果不知道还有许多记录在缓存中而去查询,你将得到根本不靠谱的结果,特别是金额计算,根本就是错误的!
我是这样解决的:强行让数据库提交,每次提交后都CHECKPOINT一下。
为何数据库设计者这么不小心,导致数据这样不可靠,难道我的理解有误吗,不知数据库高手还有什么别的办法?
...全文
402 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
仙侣步惊云 2015-04-05
  • 打赏
  • 举报
回复
还有一种可能,就是网络的设置是否影响数据的提交,例如,数据根本就没向服务器发送数据包,数据包丢失了,而delphi做的客户端程序对这种丢失没有感知?
仙侣步惊云 2015-04-05
  • 打赏
  • 举报
回复
我依然用iw,虽然水平没怎么提高,但因为对iw充满期待一直没放弃。iw最新版本是14.0.39,提供了模式对话框,这是一个切切实实的进步。 我依然用asa,虽然sybase被别人收购了,但我觉得比sqllite、mysql功能强大,比oracle和sqlsever方便,对我来说正适合。我原来使用odbc连接,现在使用oledb连接,效率有所提升。asa8.0功能已经有很大改进。我这里提出这个checkpoint只是很好奇,是不是别人也考虑过这个问题,遇到过类似的情况。我现在保存数据不再用checkpoint了,也没遇到类似的情况。 另外,我的qq是360825938,欢迎对intraweb和asa感兴趣的人与我联系,加上备注intraweb和asa即可。
仙侣步惊云 2015-04-05
  • 打赏
  • 举报
回复
我依然用iw,虽然水平没怎么提高,但因为对iw充满期待一直没放弃。iw最新版本是14.0.39,提供了模式对话框,这是一个切切实实的进步。 我依然用asa,虽然sybase被别人收购了,但我觉得比sqllite、mysql功能强大,比oracle和sqlsever方便,对我来说正适合。我原来使用odbc连接,现在使用oledb连接,效率有所提升。asa8.0功能已经有很大改进。我这里提出这个checkpoint只是很好奇,是不是别人也考虑过这个问题,遇到过类似的情况。我现在保存数据不再用checkpoint了,也没遇到类似的情况。 另外,我的qq是360825938,欢迎对intraweb和asa感兴趣的人与我联系,加上备注intraweb和asa即可。
dongqiwang 2015-03-31
  • 打赏
  • 举报
回复
sqlanywhere数据库是Sybase公司的,我在10年前用过,非主流数据库平台,powerbuild+sybase11,也经常遇到了一些莫名其妙的问题,后来公司终于08年淘汰了这个系统,转向了Oracle,楼主还在用intraWeb吗,我是看了你的帖子,果断放弃javaEE,在今年2月转向intraWeb,对Delphi程序员来说,确实开发效率很高,我现在的开发环境为DelphiXE7+intraWeb14.0.37+tms5.6.0.2,几乎是最新的,后台数据库为Oracle11G,数据库引擎为dbexpress,目前项目进展顺利,没发现什么问题,在此,对楼主表示感谢。
發糞塗牆 2015-03-30
  • 打赏
  • 举报
回复
手动checkpoint不应该出现在用户操作中,这个一般在维护操作中比较常见.数据及时性更多的应该是如何考虑把你的SQL处理得更快.
薛定谔的DBA 2015-03-29
  • 打赏
  • 举报
回复
如果是数据库的话,可能是读写分离,或者查询使用 nolock、readpast 等。否则事务是一致性的,不会出错。
leeya66 2015-03-29
  • 打赏
  • 举报
回复
几千的并发只是小数据而已,你想想淘宝的并发数, 要是都这样还怎么玩? 另外,你说的数据库太落后了,要更换掉
专注or全面 2015-03-27
  • 打赏
  • 举报
回复
后来才知道,客户端数据提交时只是保存在数据库服务器的缓存中,并不会立即更新,只会在系统设置的一个固定时间片只(例如30秒)提交给数据库磁盘文件内,而从客户端查询的数据,只是从数据库磁盘文件中取出数据查询,并不会把缓存中的记录算在内,所以,一边在大量更新提交数据库,一边要及时查询了解更新情况,如果不知道还有许多记录在缓存中而去查询,你将得到根本不靠谱的结果,特别是金额计算,根本就是错误的! 不可能是checkpoint的原因,事务提交之后,数据库会保证数据是一致的,最终是写入磁盘,但是究竟什么时候写入磁盘,是数据库自身的机制决定的。但是,不管新提交的数据有没有写入磁盘,读取数据的时候一定是读取提交后的数据,也就是说,读取数据的时候,你也没办法决定是去内存(缓存)中读取还是从磁盘中读取,但是一定会读取到的是提交后的数据,你说的这个情况,我觉得更多的问题出在应用端,而不是数据库端,事务的一致性是关系数据库最最基本的一个特征吧,后来你又说你用的sqlanywhere,没听说过这个数据库,不太清楚
Tiger_Zhao 2015-03-26
  • 打赏
  • 举报
回复
不要用 Requery(),从头开始新建对象查询。
ADO只要不是操作微软自己的数据库,不止一次碰到执行结果和文档说明不一致的情况了。

MainDataMd看起来象所有ADO对象的缓存,不是微软自己的数据库真不应该这样设计,没法保证行为和文档说明一致。
xiaoxiangqing 2015-03-26
  • 打赏
  • 举报
回复
没遇到这种情况
仙侣步惊云 2015-03-26
  • 打赏
  • 举报
回复
我基本按下面保存数据, try MainDataMd.ADOConnection1.BeginTrans; DSwfTeacher.DataSet.Post; MainDataMd.ADOConnection1.CommitTrans(); MainDataMd.ADOConnection1.Execute('CheckPoint');//强制检查点 ShowMessage('数据保存好了'); MainDataMd.ADOJsCount.Requery(); RzGlyphStatus1.Caption:= '系统共有对象'+MainDataMd.ADOJSCount.FieldByName('zs').AsString+'名,'; DSwfTeacher.DataSet.Edit; RzButton1.SetFocus; except MainDataMd.ADOConnection1.RollbackTrans(); ShowMessage('保存数据错误:可能是数据不完整、不规范,或是重复采集了人员'); end; 有完整的事务提交代码。
Tiger_Zhao 2015-03-25
  • 打赏
  • 举报
回复
数据库端不会这样的,其它会话的更新不递交会有锁存在,查询会话会等待的。
很可能你客户端的数据对象存在缓存,代码修改数据后没有马上上传到服务器上,而正常退出前肯定会把最后的更新上传的。
Q315054403 2015-03-25
  • 打赏
  • 举报
回复
不是哪个组件的BUG,是你们的设计问题,应该是嵌套事务控制上出了漏洞 如果熟悉数据库原理、机制,这个疑问就根本不会出现
仙侣步惊云 2015-03-25
  • 打赏
  • 举报
回复
从上面几位讨论看,大家似乎没有遇到我这种不可思议的问题。但故障却实实在在摆在我眼前,不过我用的不是sqlserver而是 sqlanywhere,客户端用的是 delphi+ado+odbc。 为了提高性能,我在服务器上增加了数据库的高速缓存,但自从遇到丢失数据问题后,我把缓存改为0了。 注意,要故障重现是非常难的,少量客户端操作不会有问题,只有大量用户同时更新大量数据时,故障肯定会出现的,大约千分之三左右,不过,这种结果是灾难性的,因为所有采集都必须重来。 我想,数据库设计者肯定不会让这种问题发生,否则我们的大数据云计算时代早就挂了。也许这是sqlanywhere某一版本或 delphi某个组件的bug 。有时,在delphi中使用了第三方组件可能会产生难以捕捉的错误,但愿如此。
卖水果的net 版主 2015-03-25
  • 打赏
  • 举报
回复
如果你执行了 commit 语句,那肯定会写到数据库中的,当然了,会先写 log ,其他的会话再读取,也会得新最新数据,如果你提交了 6000 行,而只得到 5992 行,应该你的程序有这种机制,点了确定后,并没有发出 commit 动作,只是在本机暂时标记了一下。
oraclecaicai 2015-03-25
  • 打赏
  • 举报
回复
数据库的缓存机制只是从物理层面提高数据库性能的设计,不会影响逻辑层面的结果。一般的数据库操作,增删改查,都要先将页面读取到缓存中。我不知道是否有方法能让程序绕过缓存,直接从文件读取数据,但正常情况下是不会发生的。 出现你所说的情况,有可能是部分客户端的更新操作没有完成造成的。如果更新操作只是一条INSERT或者UPDATE语句,那么就是程序没有把SQL语句发送到数据库;如果更新操作是多条DML语句,并且用BEGIN TRANSACTION开启了事务,那么必须要COMMIT TRANSACTION进行提交。这可以解释所有客户端退出后数据就正确了的现象,应该是程序退出时自动发送了语句或者提交了事务。 至于你说用CHECKPOINT解决了问题,我不认为是这样,这条命令的作用是把缓存中被修改过的页面写入磁盘。如之前所说,程序正常情况下不会绕开缓存读取数据。缓存中的数据是否与磁盘上一致,不会影响查询语句读取到的结果。只要你的更新语句发送到了数据库,并且提交了事务,那么从其它会话中就一定能够读取到更新的数据。而且,频繁地执行CHECKPOINT对数据库性能有很大影响。
Tiger_Zhao 2015-03-25
  • 打赏
  • 举报
回复
数据库端假如最新的数据在缓存里,查询会直接取缓存不会特地载入磁盘的就数据,不会是这个原因。
用的是纯SQL Server数据库吧?没有用外部数据?
LongRui888 2015-03-25
  • 打赏
  • 举报
回复
可以修改系统参数,来缩短 checkpoint的间隔: EXEC sys.sp_configure N'recovery interval (min)', N'1' GO RECONFIGURE WITH OVERRIDE GO
仙侣步惊云 2015-03-25
  • 打赏
  • 举报
回复
我原来也以为是客户端可能存在这种缓存,而且以前也未遇到这种问题,如果在本机上或以远程服务器上但连接用户少时,很少会有这种状况发生,只有很多客户端同时工作录入大量小笔数据时,会偶而出现丢失微量数据的情况,丢失率大概在千分之三左右。最后是强制执行CHECKPOINT后故障再没有重现。我现在每次提交数据时都CHECKPOINT下。

34,591

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧