现在有一个单机WPF程序来解析文件,然后把文件中的数据插入到数据库中,数据库是SQL SERVER 2008 R2。
数据库的表中大概是这样的结构 SEQ_ID, DATA, STAUS
其中SEQ_ID是自增或GUID,DATA存放文件解析出来的数据,STATUS表示记录的状态,插入数据时,如果数据库中存在相同DATA的记录,STATUS = 1,如果不存在相同的记录STATUS = 0.
程序采用多线程来解析文件并写入数据库,如果按照默认的数据库隔离级别,默认的锁,程序也不做同步处理,那么在插入数据库应该会出现:多个线程处理文件内容相同,在插入数据库时,都发现表中没有记录,那么就会有多条STATUS = 0,但DATA相同的记录。
目前解决办法:
1. 调高数据库的隔离级别,但是这样会影响其他程序,如WEB程序对数据库的查询等操作。
2. 把SELECT和UPDATE操作放到一个事物中处理,对事务的SELECT加上TABLOCKX独占锁,这样其他所有对这个表操作,应该都会阻塞等待。
3. 把SELECT和UPDATE操作放到一个事物中处理,并对此事务的SELECT 加上UPDLOCK更新锁,这样对于其他线程也执行这个事务时会阻塞等待。而对于其他没有加UPDLOCK锁的SELECT,会继续执行。
4. 在我程序中对多线程进行同步,对DB操作的地方加上lock锁,进行同步。这样好处就是对数据库写入是有序的,不会阻塞其他操作。
个人觉得3,4应该都可以行,就目前情况来说,因为是单机程序,对于处理文件和插入数据库的速度要求不是很高,所以采用4应该问题不到。 而外部WEB程序只会对这个表进行SELECT查询,所以用方法3,其实也不会有什么问题。
想了解一下,那种方式会比较好。 如果不是单机程序,是多个机器同时跑,应该就只能采用方法3了吧。或者还有什么其他比较好的方法?
还有个问题,对于方法3, 对SELECT使用UODLOCK锁和 在SELECT前使用update tab set status = 0 where 1 = 2; 这种效果是否一样,效率上会有区别吗?
------解决思路----------------------
因为你的 WHERE 条件是 DATA 而不是 SEQ_ID,只能全表搜索,只要有一条被锁就得等。
WITH UPDLOCK 只能在大家都用 SEQ_ID 条件时才能降低冲突。