質問

I want to execute the following two MySQL statements:

1) SELECT * FROM table1 WHERE field1=val1 FOR UPDATE;
2) UPDATE table1 SET field2=val2 WHERE field1=val1;

It is important that the second statement exactly changes the rows returned by the first statement (no additional rows and no one less). Therefore I execute the transactions with auto_commit=false and use the "for update" version of the select statement.

"For Update" locks all rows it returns, so they are in the original state when the second statement is executed. But what about insertions? Is it possible that another thread inserts a new row with field1=val1 inbetween, which then gets changed by the second statement?

And another question: Does it make a difference if the second statement doesn't changes the rows itself but does something like the following?

3) INSERT INTO table2 (SELECT * FROM table1 WHERE field1=val1)

If (3) is in the same transaction as (1), is then ensured that both selects return exactly the same elements?

edit:

I'm using InnoDB and I read some stuff about next key locking and gap locking. As far as I understood it, while executing (1), InnoDB would not only lock the selected rows but also the accessed indices.

So am I right to say that this problem doesn't occur if I have an index over column "field1"? What if there is no index for it? Is it different then?

役に立ちましたか?

解決

I can't speak to the mySQL case completely, but I rather doubt it. The only thing that SELECT FROM ... FOR UPDATE (appears) to do is preventing other transactions from modifying the given set of rows. It doesn't restrict future statements - if another row is inserted (by another transaction) before that UPDATE statement runs, it'll be updated as well.
Needless to say, the third statement you've given will also fall prey to the same issue.

What are you attempting to actually do here? It's possible there's another way to accomplish this. For example, if there's some sort of 'insertedAt' timestamp, you could probably just add that as an extra condition.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top