这篇文章主要是记录我在使用数据库中遇到的一些坑,不定期更新
## 案例一 SqlServer 2008 ##
场景:
数据对接,替合作伙伴完成影视搜索功能具体实现
合作伙伴提供数据接口,然后我们通过爬取合作伙伴的接口进行数据同步。每次我们都是全量爬取,但是入库操作是增量的。比如如果我们发现影视库中已经含有该条影视id,而且影视信息没有发生变化,那么不入库,如果已有该条影视,但是信息发生变化做update操作。如果库中没有该条影视id,做insert操作。如果全量爬取后,发现库中的某些影视id没有在这次爬取中爬到,那么对所有没有爬到的库中影视id做下线操作。当然如果发现库中已经下线的影视id,本次爬取到了,那么要做上线操作。每条影视数据,也就是对应数据库中的某一行都有相应的时间戳,表明对此次操作的时间。我们的数据平台系统不定期读取库中的数据。假如数据平台第一次全量读取库中所有的数据,同时会记录库中所有行数据中最高的时间戳。下次数据平台再次读取时,会查找大于上次时间戳的行数据,因为只有行数据中时间戳大于上次记录的时间戳,才表明数据发生了变化。然后数据平台进行建索引等等...坑
合作伙伴反映很多数据搜不到了。明明接口中有相应的影视数据,但是我们搜索不到。定位
我们发现库中其实爬取到这些影视数据,但是数据平台在读取的时候没有读取到。考虑会不会是因为时间戳的原因?
猜测:
因为插入或者修改的事务是以单条影视为事务的,所以可能存在这种情况,当数据平台开启查询事务(默认read committed),因为时间戳没有做索引,所以数据库默认做全表查询,进行到一半的时候,爬取线程开始更新数据,一共更新200条,假设已经开始更新第1条记录,记录时间戳d1 但是数据平台已经开始读到100条记录了,所以更新的第1条记录没有查到。最后数据平台查找到的更新包含第100条到200条,然后找到最大的时间戳d2。数据平台处理完毕后,记录最大的时间戳d2。因为第1条记录更新那行上次没有查找到,下次查找是以行时间戳 > d2作为条件的,因为d2 > d1 所以下次数据平台查询就没有找到上次更新过的第一条记录。这样爬取所做的更新操作没有反映到数据平台中,新增的数据没有反映到数据平台同理。-
解决方法
第一种方法:一次全量爬取所做的更新,插入或者上下线操作全部放到同一个事务中提交,这样数据平台因为是(read committed)不会出现一次查询只能查询到部分更改的情况。第二种方法:修改数据平台读取数据默认的事务级别,提高到Serializable级别,这样就不会存在数据平台开启的查询事务跟爬取线程所做的其他事务做互斥。不存在数据平台只读取到部分更改记录的情况。
第三种方法:修改数据根据上次读取到的最大时间戳做增量读取的协议。每条影视行增加两个时间戳,一个时间戳表示爬取线程做更新的最新时间戳,爬取线程每次更新影视的该时间戳。另一个时间戳表示数据平台读取该条记录的上一次时间。数据平台读取数据的条件是每行记录爬取更新的时间戳大于数据平台上一次读取的时间戳即可。
未完待续
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。