2013-04-15 159 views
1

我无法理解的场景:可以多个线程操作相同的数据库吗?

称为DBserver的进程有五个线程,每个线程都有一个连接到Mysql数据库。每次我们想要执行一个sql,我们将它发送到DBserver,然后DBserver将选择一个线程来执行。现在来了两个叫做sqlA和sqlB的sql,sqlA来自sqlB之前, 但由于DBserver使用多线程,它不能保证sqlA在sqlB之前执行。 如果sqlB真的在sqlA之前执行,在我看来,会发生错误。

例如:

sqlA:update bankTable set money = 10 where id = 10001; 

sqlB:update bankTable set money = 100 where id = 10001; 

如果SQLB sqlA之前执行,这笔钱将在10最后,这应该是100 但这DBSERVER已经上线,并没有发生任何错误,我不不知道为什么。非常感谢你!

+0

数据库服务器抛出错误的任何原因?任何方式上次更新语句将更新数据 – shola

+0

乍一看,这看起来不像是关于MySQL的问题,也不是关于你使用的任何数据库驱动程序/库。很显然,这一行的金钱价值应该是10或100,并且任何排序要求都必须在您的(pthreads)代码中实现。 如果您将* 10和100添加到现有的“金钱”余额,那么它可能是ACID合规性问题(对于依赖于存储引擎的MySQL)和您选择的连接库的线程安全性。 –

+0

@tonyli是你的问题回答? –

回答

1

为什么会出现错误?你的意思是说,它不是你期望发生的。就这样。但是这两个查询都可以按任意顺序执行,而不会出现错误。

对于这个例子,我假设sqlA总是在sqlB之前执行,因为两个查询中的工作都是相同的,并且主线程将查询传递给一个空闲线程。

但是,如果我们正在谈论更复杂的查询:我想这是表锁定进入的地方。

+0

是的,你是对的,两个查询都可以按任意顺序执行,而不会出错。但是在逻辑上,金钱变少了。也许就像吉姆丹尼斯说的那样,使用交易可以解决这个问题。 – kuangi

+0

@TonyLi我不认为交易会帮助你,当从两个不同的脚本/请求,因此2个不同的交易。但你需要做的不是“设定金钱= 10”,而是“设置金钱=金钱+ 10”或“设置金钱=金钱 - 90”。这样它会继续工作,而不用担心哪个查询先行 –

1

看起来你想要的是保持ACID合规性,同时仍然抽象单个SQL查询。

我建议的是构建一个类,该类使SQL查询接受单个SQL查询(如字符串)或SQL查询列表。该列表意味着查询是相互依赖的并且需要在相同的数据库连接上运行。

使用临时表时这一点特别重要,因为它们的作用域是数据库连接,并且通过其他连接保持不可见。

+0

是的,只使用一个连接或只使用一个线程都可以解决这个问题。谢谢。 – kuangi

+0

@TonyLi但是这会影响你的表现。可能甚至是很大的 –

+0

由于@ nl-x对其他回复进行了评论,交易可能无法帮助你。减少到1个线程会严重影响性能。我的建议汇总了作为一个单元的所有语句,只有在它们以正确的顺序运行时才会生成特定的输出。 – 0xCAFEBABE

相关问题