Edit:
Thanks to a comment by Maxim Krizhanovsky, this is all actually documented in quite a bit of detail. It's a long read, but well worth it: http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html
The really important part to note, is that the behavior of auto increment in some cases can be modified with the server setting innodb_autoinc_lock_mode including when you use INSERT ... SELECT and LOAD DATA INFILE. Some settings are not safe to use with statement based replication. The default setting is safe, but doesn't have the best performance.
Original article follows:
Using a multi-insert to save rounds trips to the database can be a great time saver, but what if you want to also retrieve all the auto-increment values from those rows you just inserted?
CREATE TABLE test ( a int unsigned auto_increment primary key ); INSERT INTO test VALUES (), (), (); SELECT LAST_INSERT_ID();
The value returned is 1, which is the first auto increment value of the multi-insert statement. This is clearly documented in the manual.
What isn't documented, is if the next two values can safely be assumed to be 2 and 3. In this simple example, with no concurrent inserts, that will be true. But will it always be true?
Luckily, the answer is yes -- at least for innodb (I haven't checked other storage engines.) Auto increment ids for a multi-insert are reserved all at once in a block. The only extra thing to be aware of, are your server's settings for
auto_increment_increment.The source code shows this:
storage/innobase/handler/ha_innodb.cc
/*********************************************************************//**
This function initializes the auto-inc counter if it has not been
initialized yet. This function does not change the value of the auto-inc
counter if it already has been initialized. Returns the value of the
auto-inc counter in *first_value, and ULONGLONG_MAX in *nb_reserved_values (as
we have a table-level lock). offset, increment, nb_desired_values are ignored.
*first_value is set to -1 if error (deadlock or lock wait timeout) */
UNIV_INTERN
void
ha_innobase::get_auto_increment(
/*============================*/
ulonglong offset, /*!< in: table autoinc offset */
ulonglong increment, /*!< in: table autoinc increment */
ulonglong nb_desired_values, /*!< in: number of values reqd */
ulonglong *first_value, /*!< out: the autoinc value */
ulonglong *nb_reserved_values) /*!< out: count of reserved values */
{