Why does MySQL increment the auto_increment value when there's a constraint violation?
Because the value is incremented outside the scope of the transaction. This is the way you want it to work, so that separate transactions can happily insert rows or roll back without waiting for each other.

If you care about gaps or want different behavior, stop using the built in and roll your own...