An SQL mode set in 2019 that nobody remembers why. An authentication plugin the driver happened to support. A charset and collation nobody chose. That is what a MySQL upgrade is made of. MySQL 9.7 LTS is out, so I am making the list again.
An LTS release of a database is a date more than a feature list. The date until which somebody else worries about patches, and the date after which the worry is yours. For a working PHP project the question is not “what is new”. It is “what did we assume”.
Assumptions accumulate. Optimizer behavior that your slowest query silently depends on. Defaults that became decisions by staying. None of it appears in code review. All of it appears in the upgrade.
So the plan is mostly archaeology. Take real queries from the production profile and compare execution plans on the old and the new server. The plans that changed are the risk list. Run migrations from zero on the new version, because migrations are code too, and they encode assumptions better than any document. Check the PHP driver and ORM compatibility matrix before anything else: cheapest check, most common failure.
Then canary. One replica on 9.7, read traffic, a week of watching. Then the rest, with a rollback path you have run at least once. Written down is a different thing.
Boring plan, on purpose. LTS is an operational choice, so the upgrade is operations. The news was on release day.
The 2019 SQL mode was mine. I still do not remember why.