shadedecho
Programmer
say i have the table
mytable:
where A is the primary key and is an auto_increment field, and the value that gets stored in B is 2 * whatever value gets stored in A from the auto_increment.
what I would like to do is be able to insert (with one insert SQL statment) and have that relationship continue, something like:
INSERT INTO `mytable` (`B`) ((LAST_INSERT_ID() + 1) * 2))
When I do this FOR THE FIRST TIME ON AN EMPTY TABLE, I do get the desired results, over and over again, in that same connection.
HOWEVER, my real question is this: Is this method multi-thread-safe... by that, I mean, would it be possible for mysql to receive 2 "INSERT" commands to the same table, starting the first command first, but then simultaneously executing the second insert, finishing with the second one before the first? Or does mysql process the INSERTS incrementally as it receives them, like putting them in a queue and doing them one at a time.
And, the bigger question is this: the mysql documentation indicates that LAST_INSERT_ID() returns an integer that is maintained "per connection", so,
what if connection "A" is created, and then connection "B" is created. now "A" starts doing something for awhile, maybe to another table, and meanwhile, "B" goes ahead and "INSERT"s into the table, and then "B" quits. Now, "A" finishes what he's doing, and he comes over and "INSERT"s into that table... IS "A"s copy of LAST_INSERT_ID() going to be updated BEFORE that insert, or after?
In my testing, this is what I've found:
It appears that "LAST_INSERT_ID()" is not set at all (defaults to 0, like all integers) for a connection until an INSERT on the table in question has been done in that connection... so, no matter what the actual last auto_increment is in a table, LAST_INSERT_ID() returns 0 for the FIRST insert, then it gets set to the correct auto_increment value. This is very troubling.
starting with a blank table, if you connected, ran the query 5 times, then disconnected, then reconnected, and ran it 5 more times, your table would look like this:
Notice how after the disconnect and reconnect, the first insert (A = 6) had a LAST_INSERT_ID() = 0 --> (0 + 1) * 2 --> 2, which got put in B. then, it got 6 assigned to it, so on the next INSERT, it was back to the sequence correctly (6 + 1) * 2 --> 14.
It also appears (as would follow from that observation) that LAST_INSERT_ID gets updated from an insert to the table by another thread ONLY after that first insert from the current thread is done, but returns 0 that first time.
So, why doesn't "LAST_INSERT_ID()" get updated AT LEAST at creation of a connection to the database? It also does not get updated if you read from the table in question first, like with a "SELECT". why not?
or better yet, why doesn't it (at the time its used) check the table for the value of "next auto_increment" and return - 1 of that?
from my testing, it appears that not only is LAST_INSERT_ID() not multi-thread-safe... its not even safe to use for the first insert to a table in ONE thread.
So, LAST_INSERT_ID(), in its non-multi-threaded, non-connection-updated form, is hardly useful for anything!!! The only way LAST_INSERT_ID() could be useful is in a SINGLE-THREADED (how many mysql applications are actually single-user?) application, and even then, only when you had already executed at least one INSERT to the table!!!!
Anyone got any thoughts? I need to be able to "know" in an INSERT statement what value is being assigned to the auto_increment field in that same INSERT statement. anyone got a workaround? Anyone know why MySQL would have a function like that which is so deliberately NON-MULTI-THREAD-SAFE?
mytable:
Code:
+-----+-----+
| A | B |
+-----+-----+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |
+-----+-----+
where A is the primary key and is an auto_increment field, and the value that gets stored in B is 2 * whatever value gets stored in A from the auto_increment.
what I would like to do is be able to insert (with one insert SQL statment) and have that relationship continue, something like:
INSERT INTO `mytable` (`B`) ((LAST_INSERT_ID() + 1) * 2))
When I do this FOR THE FIRST TIME ON AN EMPTY TABLE, I do get the desired results, over and over again, in that same connection.
HOWEVER, my real question is this: Is this method multi-thread-safe... by that, I mean, would it be possible for mysql to receive 2 "INSERT" commands to the same table, starting the first command first, but then simultaneously executing the second insert, finishing with the second one before the first? Or does mysql process the INSERTS incrementally as it receives them, like putting them in a queue and doing them one at a time.
And, the bigger question is this: the mysql documentation indicates that LAST_INSERT_ID() returns an integer that is maintained "per connection", so,
what if connection "A" is created, and then connection "B" is created. now "A" starts doing something for awhile, maybe to another table, and meanwhile, "B" goes ahead and "INSERT"s into the table, and then "B" quits. Now, "A" finishes what he's doing, and he comes over and "INSERT"s into that table... IS "A"s copy of LAST_INSERT_ID() going to be updated BEFORE that insert, or after?
In my testing, this is what I've found:
It appears that "LAST_INSERT_ID()" is not set at all (defaults to 0, like all integers) for a connection until an INSERT on the table in question has been done in that connection... so, no matter what the actual last auto_increment is in a table, LAST_INSERT_ID() returns 0 for the FIRST insert, then it gets set to the correct auto_increment value. This is very troubling.
starting with a blank table, if you connected, ran the query 5 times, then disconnected, then reconnected, and ran it 5 more times, your table would look like this:
Code:
+-----+-----+
| A | B |
+-----+-----+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |
| 5 | 10 |
| 6 | 2 |
| 7 | 14 |
| 8 | 16 |
| 9 | 18 |
| 10 | 20 |
+-----+-----+
Notice how after the disconnect and reconnect, the first insert (A = 6) had a LAST_INSERT_ID() = 0 --> (0 + 1) * 2 --> 2, which got put in B. then, it got 6 assigned to it, so on the next INSERT, it was back to the sequence correctly (6 + 1) * 2 --> 14.
It also appears (as would follow from that observation) that LAST_INSERT_ID gets updated from an insert to the table by another thread ONLY after that first insert from the current thread is done, but returns 0 that first time.
So, why doesn't "LAST_INSERT_ID()" get updated AT LEAST at creation of a connection to the database? It also does not get updated if you read from the table in question first, like with a "SELECT". why not?
or better yet, why doesn't it (at the time its used) check the table for the value of "next auto_increment" and return - 1 of that?
from my testing, it appears that not only is LAST_INSERT_ID() not multi-thread-safe... its not even safe to use for the first insert to a table in ONE thread.
So, LAST_INSERT_ID(), in its non-multi-threaded, non-connection-updated form, is hardly useful for anything!!! The only way LAST_INSERT_ID() could be useful is in a SINGLE-THREADED (how many mysql applications are actually single-user?) application, and even then, only when you had already executed at least one INSERT to the table!!!!
Anyone got any thoughts? I need to be able to "know" in an INSERT statement what value is being assigned to the auto_increment field in that same INSERT statement. anyone got a workaround? Anyone know why MySQL would have a function like that which is so deliberately NON-MULTI-THREAD-SAFE?