Applying Schema Changes

What setup:upgrade compares, how --dry-run shows you the SQL first, and the order the commands go in on production.

Syntaxbin/magento setup:upgrade --dry-run=1

bin/magento setup:upgrade is the command that turns declarations into tables. It builds the desired schema by merging db_schema.xml from every enabled module, reads the actual schema from the database, and applies the difference. In the same run it registers any newly enabled modules and applies data patches.

Looking before you leap

bin/magento setup:db:status answers one question: does the database match the code? It prints All modules are up to date. or Run 'setup:upgrade' to update your DB schema and data.

bin/magento setup:upgrade --dry-run=1 goes further. The database is left untouched and the statements that would have run are written to var/log/dry-run-installation.log. On a sales_order table with millions of rows, reading that file is the difference between a two-second deploy and a locked table. An ALTER TABLE that rebuilds a large table is a maintenance window, not a deploy step.

Narrower commands

setup:db-schema:upgrade applies schema changes only and setup:db-data:upgrade applies data changes only. setup:upgrade runs both in the right order and is the normal choice.

What trips people up

In production mode setup:upgrade clears generated code unless you pass --keep-generated, and the site serves errors until bin/magento setup:di:compile finishes. Enable maintenance mode first.

Example

Example · bash
# check whether anything is pending
bin/magento setup:db:status
# All modules are up to date.

# after pulling a branch that adds a column
bin/magento setup:db:status
# Run 'setup:upgrade' to update your DB schema and data.

# see the plan, change nothing
bin/magento setup:upgrade --dry-run=1
# Upgrade completed successfully.

tail -n 4 var/log/dry-run-installation.log
# ALTER TABLE `soundscode_enquiry` ADD COLUMN `is_archived` smallint(6) NOT NULL DEFAULT 0 COMMENT 'Is archived'
# ALTER TABLE `soundscode_enquiry` ADD INDEX `SOUNDSCODE_ENQUIRY_EMAIL` (`email`)

# apply it
bin/magento setup:upgrade
# Upgrade completed successfully.

When to use it

  • Check whether a pulled branch needs a schema upgrade before running anything.
  • Read the exact ALTER TABLE statements a release will run on production.
  • Sequence the deploy commands so the storefront is never serving a half-upgraded database.
  • Diagnose a schema change that appeared to apply but did not.

More examples

The production order

Maintenance mode first, because the database is mid-change while setup:upgrade runs and a request arriving against a half-altered table fails in ways that are hard to read later. --keep-generated is what stops setup:upgrade throwing away the generated/ directory your build pipeline already produced; without it, the first request after the upgrade has to compile and the site is slow or broken until it does.

Example · bash
bin/magento maintenance:enable

# keep the compiled DI and generated factories that the build produced
bin/magento setup:upgrade --keep-generated

# only needed if the release changed constructors or added plugins
bin/magento setup:di:compile
bin/magento setup:static-content:deploy en_GB

bin/magento cache:flush
bin/magento maintenance:disable

Reading a dangerous dry run

A MODIFY COLUMN on an InnoDB table of that size can rebuild the whole table while holding it against writes. This is the moment to decide whether the change ships in a maintenance window, or goes out through an online schema change tool outside Magento instead. Grep the dry-run log for the big core tables - sales_order, sales_order_item, quote, catalog_product_entity - before every release.

Example · bash
bin/magento setup:upgrade --dry-run=1
grep -i 'sales_order' var/log/dry-run-installation.log

# ALTER TABLE `sales_order` MODIFY COLUMN `customer_note` text NULL COMMENT 'Customer Note'

# how big is the table actually?
mysql -e "SELECT table_rows FROM information_schema.tables
          WHERE table_name = 'sales_order'" magento
# 4812337

When setup:upgrade appears to do nothing

The commonest false alarm. A disabled module contributes no declarations, so there is no difference to apply and the command honestly reports success. Check module:status before suspecting the XML. The same reasoning covers a module whose folder name does not match the name in registration.php: Magento never sees it, so it is neither enabled nor broken.

Example · bash
bin/magento module:status Soundscode_Enquiry
# Module is disabled

bin/magento setup:upgrade
# Upgrade completed successfully.

# no table, and no error
bin/magento setup:db:status
# All modules are up to date.

Discussion

  • Be the first to comment on this lesson.