Something that jumps out at me but doesn't explain your problem is that $! is for system errors not DBI errors. Those would be in $DBI::errstr, or you could just set RaiseError in the connect. But like I said, that doesn't explain this behavior unless there's some other loop around this loop that you're not showing.
Thanks. The code is complete. My big piece of code was using up lot of CPU cycles and I then narrowed down to his chunk of code. This snippet of code when I run after the first sleep becomes an insomniac.