2015-05-29 55 views
2

在我的应用程序(VC++/Windows 8)中,我有7个线程每个都打开了连接到MySQL数据库。所有这些线程同时尝试增加表中单个字段的值。MySQL:简单表上的并发更新(通过线程)

要做到这一点,我已经创建有列MyIndexMyCounter(均为整数)示例表DEMO_TABLE并加入一排有MyIndex字段值0。然后,我通过使用MySQL连接C++每个线程调用executeUpdate

executeUpdate("UPDATE DEMO_TABLE SET MyCounter = (MyCounter + 1) WHERE MyIndex = 0"); 

这里我没有使用任何锁定(行或表锁)仍然代码没有给我任何错误或例外。当我检查MyCounter的值时,我看到它增加了。所以这似乎是正确的。

但已经提出了我这些问题:

  1. 默认情况下,MySQL使用它需要锁定表并发更新查询执行MyISAM引擎。但是我没有在这里锁表,这个代码如何工作而不会抛出任何异常?

  2. executeUpdate是否隐式使用任何锁?

(按我的知识InnoDB提供行级锁定机制,我计划在我的代码使用。但在此之前,我只是想对我自己尝试用默认的引擎发生了什么,没有任何锁。我期待我会得到一些异常,这将告诉我有关竞态条件,以便我可以验证相同情况不会发生与使用锁定)

回答

1

锁定是隐含的,是的,但它不是由executeUpdate()完成。 MySQL中的存储引擎处理锁定和解锁。

无论您何时写入MyISAM表,您的查询都会等待表上的写锁定可用,获取写锁定,写入完成,并释放写入锁定。在MyISAM中没有真正的写入并发,因为每个工作者实际上都在等待写入锁定。由于写入请求已序列化,因此不会出现错误。

InnoDB与InnoDB的情况很相似,但差别很大,因为InnoDB只锁定表的一部分,通常在行级别,InnoDB可以在索引内锁定一个范围,从而锁定该范围内的行指数(以及它们之前的差距)。这种锁定比表锁定更细化,允许改进并发行为,但同一行没有并发操作 - 每个工作者等待它所需的锁定或锁定。

在这两种情况下,锁都是隐含的。

+0

非常感谢。这清除了大部分空气。但我想知道他们为什么提供了'SELECT ... FOR UPDATE'和'SELECT ... LOCK IN SHARE MODE'查询?隐式锁定可以在不需要应用程序的情况下管理行级别的锁,不必担心它。那么在什么情况下应用程序需要发布这些查询呢? – Atul

+1

'SELECT'的这些变体适用于InnoDB;例如,它们用于需要读取记录的事务中,进行一些计算,然后更新相同的记录,而不会有任何其他连接偷偷摸摸并且弄乱它。在MyISAM中,您已经手动使用'LOCK TABLE ... WRITE'来获得相同的效果。 –

+2

你的例子是一个原子'UPDATE'递增列。自动锁定(通过MyISAM或InnoDB)对于_single_语句已足够。 –