在我的应用程序(VC ++ / Windows 8)中,我有7个线程,每个线程都打开了与MySQL数据库的连接。所有这些线程同时尝试增加表中单个字段的值。
为此,我创建了一个包含MyIndex
和MyCounter
列(两个整数)的示例表DEMO_TABLE,并为其添加了一行MyIndex
字段值为0.然后我就是使用 MySQL Connector C ++ :
executeUpdate
executeUpdate("UPDATE DEMO_TABLE SET MyCounter = (MyCounter + 1) WHERE MyIndex = 0");
这里我没有使用任何锁定(行或表锁)仍然代码没有给我任何错误或异常。当我检查MyCounter
的值时,我看到它增加了。所以这似乎是正确的。
但是我提出了这些问题:
默认情况下,MySQL使用MyISAM引擎,该引擎需要锁定表以执行并发更新查询。但我不是在这里锁定表,这段代码如何工作而不抛出任何异常?
executeUpdate是否隐式使用任何锁?
(根据我的知识,InnoDB提供了我计划在我的代码中使用的行级锁定机制。但在此之前,我只是想尝试自己的默认引擎没有任何锁定会发生什么。我期待我会得到一些将告诉我有关竞争条件的异常,以便我可以使用锁来验证相同的情况
答案 0 :(得分:1)
锁定是隐含的,是的,但executeUpdate()
没有完成。 MySQL中的存储引擎处理锁定和解锁。
每当您写入MyISAM表时,您的查询都会等待表上的写锁定可用,获取写锁定,写入完成以及释放写入锁定。 MyISAM中没有真正的写并发,因为每个worker实际上都在排队等待写锁定。您没有收到错误,因为写请求已被序列化。
InnoDB的情况类似但非常不同,因为InnoDB只锁定表的一部分,通常在行级别,InnoDB可以锁定索引中的范围,从而锁定索引中该范围的行(以及它们之前的差距)。此锁定比表锁定更精细,允许改进的并发行为,但同一行上没有并发操作 - 每个工作程序等待它所需的锁定或锁定。
在这两种情况下,隐式采取锁定。