文档介绍:如何处理大量数据如何处理几十万条并发数据(2010-03-18 20:51:54) 比如我们在 SQL Serve r 中的表中定义一个字段为 timestam p 类型的字段 ts, 这个字段的值不需要我们进行控制的。在 Insert 与 Update 时, 数据库会自己进行 ts 值的更新, 因此我们只要在 Update 时使用: Update xxx where key=***@key and ts=***@ts 就可以了,根本不用考虑 ts 里的值更新。 Delete 时也最好进行一下判断, 用这种方式是可以控制数据并发操作的。只需要在 Update 与 Delete 时, 判断" 影响条数" 就可以知道更新是否成功。这一点我想非常方便,但不是所有的数据库都支持 timestampr 的, 如在 Access 里没有 timestamp 字段,我也不知道其他的数据库是否都有类似的 timestamp 类型, 不管怎么样, 我觉得我们不能完全信赖于数据库的控制, 而应该采用自设的控制机制, 这样可以适应系统的数据库移值,下面我就介绍一下, 下如何实现,自设的时间戳控制。我们也同样建一个字段 ts ,定义为 Varchar ,长度在 20 以上即可, 而且不允许为 null ,这样比较合适。我们应该采用什么机制来生成随时的或者说不可能会产生一样的值, 我推荐的是 , 这是一个 12 位的数字, 由于在 Update 等更新时, 数据库会自动进行锁定, 所以不可能会在同一时间会有两个一样的操作执行, 因此这就可以避免 Ticks 产生相同的值了。或者也可以采用 Guid 值,也可以产生唯一值,但我觉得 Guid 值太大,可能会影响效率。那好,在我们 Insert 时:Insert xxxx ts='221283747584' where key='1' 在 Update 时 Update xx set xxx ts='39383848593839' where key='1' and ts='1**********' // 假设取到的原值为'**********' Delete 类似上面的。我们判断影响条数,如果为 0 则说明更新不成功。我相信上面的方法是简单可行的。我目前也遇到一个问题:如果是批量更新与批量删除,如何进行并发控制呢? 由于批量更新时,不是一条记录: Update xxx where Birthday='2004-2-1' 之类的,会影响到 N 条数据,要进行并发控制就不那么容易了。如果还是采用一条条判断 ts 那是不现实的。对于这种只能放弃并发控制吗? 在多线程编程时,开发人员经常会遭遇多个线程读写某个资源的情况。这就需要进行线程同步来保证线程安全。一般情况下, 我们的同步措施是使用锁机制。但是, 假如线程只对资源进行读取操作, 那么根本不需要使用锁; 反之, 假如线程只对资源进行写入操作, 则应当使用互斥锁( 比如使用 Monitor 类等) 。还有一种情况,就是存在多个线程对资源进行读取操作, 同时每次只有一个线程对资源进行独占写入操作。这正是本文主题-- 读写锁的用武之地。 ReaderWriterLock Framework BCL 在 版本时,给我们提供了一个 ReaderWriterLock 类来面对此种情景。但是很遗憾, Microsoft 官方不推荐使用该类。 Jeffrey Richter 也在他的《 CLR via C# 》一书中对它进行了严厉的批判。下面是该类不受欢迎的主要原因: 性能。这个类实在是太慢了。比如它的 AcquireReaderLock 方法比 Monitor 类的 Enter 方法要慢 5 倍左右,而等待争夺写锁甚至比 Monitor 类慢 6 倍。策略。假如某个线程完成写入操作后, 同时面临读线程和写线程等待处理。 ReaderWriterLock 会优先释放读线程,而让写线程继续等待。但我们使用读写锁是因为存在大量的读线程和非常少的写线程, 这样写线程很可能必须长时间地等待, 造成写线程饥饿, 不能及时更新数据。更槽糕的情况是, 假如写线程一直等待, 就会造成活锁。反之, 我们让 ReaderWriterLock 采取写线程优先的策略。如果存在多个写线程,而读线程数量稀少,也会造成读线程饥饿。幸运的是, 现实实践中, 这种情况很少出现。一旦发生这种情况, 我们可以采取互斥锁的办法。递归。 ReaderWriterLock 类支持锁递归。这就意味着该锁清楚的知道目前哪个线程拥有它。假如拥有该锁的线程递归尝试获得该读写锁,递归算法允许该线程获得该读写锁,并且增加获得该锁的计数。然而该线程必须释放该锁相同的次数以