It's nearly impossible to avoid deadlock in any reasonable complex use of MySQL.
It's usually the gap locks that bite you, I've found.
https://www.percona.com/blog/2012/03/27/innodbs-gap-locks/
Oh, and do all your deletes by primary key. Deletes with joins are especially good for creating too many locks.
It's nearly impossible to avoid deadlock in any reasonable complex use of MySQL.