This makes error handling a lot easier. If you have an error, you just abort the current transaction. You don’t have to worry about undoing previous database changes.

Changes made in a transaction are either saved in their entirety or not at all.

Transactions allow multiple logical threads (threads or processes) to access databases and the database prevents the threads from making conflicting changes.

This allows you to scale your application across multiple threads, processes or machines without having to use low-level locking primitives.

You still have to deal with concurrency on some level. For timestamp-based systems like ZODB, you may have to retry conflicting transactions. With locking-based systems, you have to deal with possible deadlocks.