sqlserver 多线程读取重复问题数据防止出现重复

java多线程读取数据库最后汇总_百度知道
java多线程读取数据库最后汇总
您的回答被采纳后将获得:
系统奖励20(财富值+经验值)+难题奖励30(财富值+经验值)
我有更好的答案
创建数据库
选择开始菜单中→程序→【Management SQL Server 2008】→【SQL Server Management Studio】命令,打开【SQL Server Management Studio】窗口,并使用Windows或 SQL Server身份验证建立连接。
在【对象资源管理器】窗口中展开服务器,然后选择【数据库】节点
右键单击【数据库】节点,从弹出来的快捷菜单中选择【新建数据库】命令。
执行上述操作后,会弹出【新建数据库】对话框。在对话框、左侧有3个选项,分别是【常规】、【选项】和【文件组】。完成这三个选项中的设置会后,就完成了数据库的创建工作,
在【数据库名称】文本框中输入要新建数据库的名称。例如,这里以“新建的数据库”。
在【所有者】文本框中输入新建数据库的所有者,如sa。根据数据库的使用情况,选择启用或者禁用【使用...
其他类似问题
为您推荐:
您可能关注的推广
多线程的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁数据库脏读、不可重复读、幻象读(收藏) - Sun_Blue_Sky - 博客园
菩提本无树,明镜亦非台,本来无一物,何处惹尘埃
寻求内心的平静
posts - 21, comments - 75, trackbacks - 0, articles - 93
数据库的事务隔离级别(TRANSACTION ISOLATION LEVEL)是一个数据库上很基本的一个概念。为什么会有事务隔离级别,SQL Server上实现了哪些事务隔离级别?事务隔离级别的前提是一个多用户、多进程、多线程的并发系统,在这个系统中为了保证数据的一致性和完整性,我们引入了事务隔离级别这个概念,对一个单用户、单线程的应用来说则不存在这个问题。
首先,我们来看一下高并发的系统中会存在哪些问题,为了便于理解我们以张三在招商银行的账号和存款为例。
一、准备工作:
1. 创建一个银行账号Table(只是为了说明问题,不考虑表的设计范式)CREATE TABLE
dbo.BankAccount(
BankAccountId
NOT NULL, -- 银行账号
NVARCHAR(32)
NOT NULL, -- 用户
DECIMAL(19, 2)
NOT NULL, -- 余额
LastUpdate
SMALLDATETIME
NOT NULL)GO
2. 准备数据INSERT INTO
dbo.BankAccount
VALUES ('1120', N'张三', 10000.00, GETDATE()) -- 北京分行账号INSERT INTO
dbo.BankAccount
VALUES ('7787', N'张三', 20000.00, GETDATE()) -- 深圳分行账号GO
3. 查看数据SELECT * FROM
dbo.BankAccount
二、应用场景
假设张三在招商银行开设了两个账号,一个是招商银行北京分行,一个是招商银行深圳分行,两个账号的余额分别是10,000和20,000。
1. 张三在网上做了一笔交易,交易额100,买方小王通过银行汇款100到张三的北京分行的账号(见下面左图),柜台操作人员向张三账号存入100(事务一),然后系统些操作日志(假设需要10秒,WAITFOR
'00:00:10')正在此时张三在ATM查了一下账号上余额(事务二),发现已经是10100,于是回去准备发货,但是事务一在写操作日志时超时,这是事务回滚,存款交易被取消,钱退给了小王,这样张三查到的账号余额事实上是事务一还没有提交的数据,导致张三错误的认为已经收到交易款项。
数据库的事务隔离级别(TRANSACTION
ISOLATION LEVEL)是一个数据库上很基本的一个概念。为什么会有事务隔离级别,SQL
Server上实现了哪些事务隔离级别?事务隔离级别的前提是一个多用户、多进程、多线程的并发系统,在这个系统中为了保证数据的一致性和完整性,我们引入了事务隔离级别这个概念,对一个单用户、单线程的应用来说则不存在这个问题。
首先,我们来看一下高并发的系统中会存在哪些问题,为了便于理解我们以张三在招商银行的账号和存款为例。
一、准备工作:
1. 创建一个银行账号Table(只是为了说明问题,不考虑表的设计范式)CREATE TABLE
dbo.BankAccount(
BankAccountId
NOT NULL, -- 银行账号
NVARCHAR(32)
NOT NULL, -- 用户
DECIMAL(19, 2)
NOT NULL, -- 余额
LastUpdate
SMALLDATETIME
NOT NULL)GO
2. 准备数据INSERT INTO
dbo.BankAccount
VALUES ('1120', N'张三', 10000.00, GETDATE()) -- 北京分行账号INSERT INTO
dbo.BankAccount
VALUES ('7787', N'张三', 20000.00, GETDATE()) -- 深圳分行账号GO
3. 查看数据SELECT * FROM
dbo.BankAccount
二、应用场景
假设张三在招商银行开设了两个账号,一个是招商银行北京分行,一个是招商银行深圳分行,两个账号的余额分别是10,000和20,000。
1. 张三在网上做了一笔交易,交易额100,买方小王通过银行汇款100到张三的北京分行的账号(见下面左图),柜台操作人员向张三账号存入100(事务一),然后系统些操作日志(假设需要10秒,WAITFOR
'00:00:10')正在此时张三在ATM查了一下账号上余额(事务二),发现已经是10100,于是回去准备发货,但是事务一在写操作日志时超时,这是事务回滚,存款交易被取消,钱退给了小王,这样张三查到的账号余额事实上是事务一还没有提交的数据,导致张三错误的认为已经收到交易款项。 一个事务读到另外一个事务还没有提交的数据,我们称之为脏读。解决方法:把事务隔离级别调整到READ
COMMITTED,即把右上图中的SET TRAN ISOLATION LEVEL READ UNCOMMITTED更改成下图中的SET TRAN
ISOLATION LEVEL READ
COMMITTED。这时我们重复上面的动作会发现事务二会一直等到事务一执行完毕再返回结果,因为此时事务以已经把自己的更改ROLLBACK了,所以事务二可以返回正确的结果。
2. 张三先后两次查询某一账号的余额,在两次查询期间,小王完成了银行转账,导致两次的查询结果不同。
一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。解决方法:把事务隔离级别调整到REPEATABLE
READ。在下图中使用SET TRAN ISOLATION LEVEL REPEATABLE
READ。这时我们重复上面的动作会发现事务二会一直等到事务一执行完毕再返回结果。
3. 张三妻子先后两次查询张三招商银行所有账号的总余额,而在此期间张三在广州招商银行分行成功开设了一个账号,并存入5000,导致张三妻子两次查询的总余额不同,在此期间张三原有两个账号的余额均未发生改变。 一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读。解决方法:把事务隔离级别调整到SERIALIZABLE。在下图中使用SET
TRAN ISOLATION LEVEL SERIALIZABLE。这时我们重复上面的动作会发现事务二会一直等到事务一执行完毕再返回结果。
事务隔离级别是通过数据库的锁机制来控制的,在不同的应用场景需要应用不同的事务隔离级别,SQL Server默认的事务隔离级别是READ
COMMITTED,默认的隔离级别,已经可以满足我们大部分应用的需求。多线程,数据并发锁表问题
[问题点数:50分,结帖人wdx2008]
多线程,数据并发锁表问题
[问题点数:50分,结帖人wdx2008]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
本帖子已过去太久远了,不再提供回复功能。在SQLServer中怎么防止多线程程序同事查询到同一条数据?
[问题点数:50分,结帖人vick]
在SQLServer中怎么防止多线程程序同事查询到同一条数据?
[问题点数:50分,结帖人vick]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2010年7月 荣获微软MVP称号
2008年11月 MS-SQL Server大版内专家分月排行榜第一2008年10月 MS-SQL Server大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。3588人阅读
C/C++学习(56)
数据库学习(21)
&&&&&&& 书写一存储过程:proc_importurltodb;
&&&&&&& 该存储过程的主要作用是将给定的URL拆分,以类链表的方式多个表分层次给予存储。
&&&&&&& 主要的流程为: 首先查询表,判断要插入的数据是否存在;如果存在,则返回相应的orderid;如果不存在,则插入数据,并且返回插入后的orderid。
&&&&&&& 由于数据量较大(千万级),因此程序中采用了ADO+多线程调用存储过程的方式,结果跑了一天的数据发现出现问题了;
由于多线程问题,可能会出现线程1插入同样数据,与此同时线程2插入同样数据,但由于库中没有要插入的数据,因此线程1和线程2会分别将数据给予插入,结果为同样的数据却出现了重复。。。。
&&&&& 呵呵,每天都例行公事,出点棘手的问题。没办法只能解决处理了:
&&&&& 方法一:数据库锁定
&&&&&& 由于是多线程调用存储过程,而整个插入逻辑都由存储过程实现,因此如果需要锁定数据,仅能靠存储过程中实现。
通过查看sql server 帮助手册以及试验,发现采用
&&&& begin tran
&&&& SET @OrderNum = (SELECT& top 1 urldomainorderid FROM UrlDomainTable with(tablockx) & WHERE urlinfo = @UrlDomain)
&&&& commit tran
& 的方式可以确保插入时为唯一条数据。
& & && 但却也出现新问题了: 由于采用的是表级锁定, 在存储过程的整个事务中,其它事务无法使用该表;而整个系统的其它表则会同时使用该表。。。所以再换思路。
&&&&&&& 方法二:多线程同步
&&&&&&&& 该方法需要对含有同样数据的信息进行多线程同步处理,主要思路为多线程插入数据时,判断是否为同样数据,如果同样,则同步。
&&&&&&& 实现复杂,不想实现~~&
&&&&&&&& 方法三:唯一约束+错误处理
&&&&&& 对插入数据表的特定列创建唯一约束,对于可能会涉及到多个列的,则创建组合唯一约束。
当出现相同数据多次插入时,则会由于唯一约束问题,而插入失败。此时通过TRY ....CATCH即可捕获错误信息,通过对错误信息判断,进而可以再次插入数据,而此时由于数据已经存在因此也就不存在多次插入的可能。
&&&&&&&& 呵呵,问题总算得到解决,又得到一个教训。。。700多W白跑了。
&&&&&&&& 不知道,各位看有没有其它更好的办法?
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:297058次
积分:3756
积分:3756
排名:第5807名
原创:65篇
转载:146篇
评论:49条
(1)(1)(6)(1)(1)(2)(3)(2)(2)(1)(1)(3)(2)(1)(1)(1)(6)(3)(1)(1)(2)(1)(5)(1)(3)(7)(2)(3)(5)(3)(5)(2)(3)(4)(1)(7)(16)(13)(16)(15)(9)(12)(19)(6)(10)(1)

我要回帖

更多关于 sql server 多线程 的文章

 

随机推荐