简体   繁体   English

MyISAM和InnoDB中的单个mysql语句是否是原子的?

[英]Are single mysql statements atomic in MyISAM and InnoDB?

For example, I have a row with a column C1 value = 'clean' , and two different clients run this query at the same time : 例如,我有一列一列C1 value = 'clean' ,和两个不同的客户端运行在同一时间这个查询:

update T1 set C1 = 'dirty' where Id = 1

Without using transactions, is it guaranteed regardless of engine type that the value of mysql_affected_rows() would be 1 for one client and 0 for the other? 在不使用事务的情况下, 无论引擎类型如何 ,都保证 mysql_affected_rows()的值对于一个客户端为1对于另一个客户端为0

Yes and No :-) 是和否:-)

In both cases, the access is serialised (assuming you're using a transactional engine like InnoDB) since they hit the same row, so they won't interfere with each other. 在这两种情况下, 访问都是序列化的 (假设您正在使用像InnoDB这样的事务引擎),因为它们在同一行中,因此它们不会相互干扰。 In other words, the statements are atomic. 换句话说,这些陈述原子的。

However, the affected row count actually depends on your configuration set when you open the connection. 但是,受影响的行数实际上取决于打开连接时的配置集。 The page for mysql_affected_rows() has this to say (my bold): mysql_affected_rows()页面有这个说(我的粗体):

For UPDATE statements, the affected-rows value by default is the number of rows actually changed . 对于UPDATE语句,默认情况下受影响的行值是实际更改的行数。 If you specify the CLIENT_FOUND_ROWS flag to mysql_real_connect() when connecting to mysqld, the affected-rows value is the number of rows "found" ; 如果在连接到mysqld时指定了mysql_real_connect()的CLIENT_FOUND_ROWS标志,则受影响的行值是“找到”的行数; that is, matched by the WHERE clause. 也就是说,由WHERE子句匹配。

And from the mysql_real_connect page : 并从mysql_real_connect页面

CLIENT_FOUND_ROWS: Return the number of found (matched) rows, not the number of changed rows. CLIENT_FOUND_ROWS:返回找到的 (匹配的)行数,而不是已更改的行数。

So, in terms of what happens with CLIENT_FOUND_ROWS being configured, the affected rows for: 那么,在什么情况条件CLIENT_FOUND_ROWS配置,则受影响的行为:

UPDATE T1 SET C1 = 'dirty' WHERE id = 1

have nothing to do with whether the data is changed, only what rows matched. 与数据是否更改 无关 只与哪些行匹配。 This would be 1 for both queries. 对于两个查询,这将是1。

On the other hand, if CLIENT_FOUND_ROWS was not set, the second query would not actually be changing the row (since it's already populated with 'dirty') and would have a row count of zero. 另一方面,如果设置CLIENT_FOUND_ROWS ,则第二个查询实际上不会更改该行(因为它已经填充了'dirty')并且行计数为零。

If you wanted the same behaviour regardless of that setting (only showing changes), you could use something like: 如果您想要相同的行为而不管该设置(仅显示更改),您可以使用以下内容:

UPDATE T1 SET C1 = 'dirty' WHERE id = 1 AND C1 <> 'dirty'

如果您使用像InnoDB这样的事务存储引擎,MySQL将符合ACID标准。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM