I like Udi Dahan's post about CQRS the most, and I take an example from there:
Let’s say we have a customer service representative who is one the
phone with a customer. This user is looking at the customer’s details
on the screen and wants to make them a ‘preferred’ customer, as well
as modifying their address, changing their title from Ms to Mrs,
changing their last name, and indicating that they’re now married.
What the user doesn’t know is that after opening the screen, an event
arrived from the billing department indicating that this same customer
doesn’t pay their bills – they’re delinquent. At this point, our user
submits their changes.
Should we accept their changes?
Well, we should accept some of them, but not the change to
‘preferred’, since the customer is delinquent.
And, concerning your question
But how is that not possible with everyday CRUD operations?
There is no such thing as command in CRUD by definition. In CRUD we have only, um, CRUD: create, read, update and delete. So that's how command imitation with CRUD looks like (again, it's an excerpt from Udi Dahan's post):
But writing those kinds of checks is a pain – we need to do a diff on
the data, infer what the changes mean, which ones are related to each
other (name change, title change) and which are separate, identify
which data to check against – not just compared to the data the user
retrieved, but compared to the current state in the database, and then
reject or accept.
It's not only about performance. It's also about enhancing overall user experience. If the command is valid, that is, date ranges, emails, etc (which can be ensured on the client side), server does not have to return any errors most of the time. It can handle any inconsistencies caused by parallel commands asynchronously, and notifying a client with, say, an email. This became possible, as Constantin Galbenu also said, because commands capture a business intent. In case of any "race condition" you can ask your domain expert what to do and he'll be able to answer.