Is this understanding correct?
Basically, but you've failed to account for the small size of the header nonce space (32 bits) and the speed of modern hardware (on the order of 10 terrahashes per second per miner).
A 32 bit nonce can only provide
2 ** 32 = ~4 billion combinations. That corresponds to 4 gigahashes. A single modern miner can do more than a thousand times in half a second, so the nonce space is almost always exhausted without finding a block.
When Bitcoin hash rate was first increasing through the FPGA and early ASIC eras, nTime rolling was implemented so that miners didn't have to make significant changes to their hardware and software to deal with the problem of nonce space exhaustion. However, that hack of a solution was increasingly less useful the faster hardware got, as a typical block can only move time around in a range of about two hours (3,600 one-second increments) and sometimes much less than that (this is especially the case when other miners are using nRollTime as they can use up the acceptable time values available to subsequent miners).
The correct solution was to put an extra nonce in the coinbase field of the generation transaction, something that was actually implemented in the original Bitcoin 0.1 software. Changing any transaction in the block also changes the 256-bit merkle root in the block header, eliminating the risk of nonce space exhaustion. This technique is now universally used by Bitcoin miners and usually implemented directly in the hardware (I think usually using a small FPGA for the extra nonce updates and merkle root regeneration).
 The coinbase field currently allows miners to add up to 96 arbitrary bytes without affecting any protocol features. The company Coinbase is named after this field but has no other relationship to it.