Chapter 11 · Views, Stored Programs, Triggers, Events, and SQL/PSM

Server-Side Logic Testing, Deployment, Privileges, and Application-Boundary Decisions

Deploy MariaDB views, routines, triggers and events as versioned production objects with definer/grant validation, dependency order, SHOW CREATE evidence, rollback plans and explicit database-versus-application ownership criteria.

Advanced130–150 minutesStored-object deployment + boundary labMariaDB Community 12.3.2 baselineCurriculum anchor: 11.8 LTS · verify target versionLast reviewed: August 2026

Learning outcomes

A release can pass application tests and still fail in production because a restored view names a missing definer, a trigger is created before the routine it calls, an event becomes enabled before its grants are ready, or a rollback script restores table DDL but not stored objects. Server-side logic is executable production code. It needs source control, dependency order, privilege review, repeatable tests, deployment evidence and a decision about whether the database is actually the right ownership boundary.

01

Build a deployment manifest for views, routines, triggers and events with explicit owners and dependencies.

02

Capture canonical SHOW CREATE definitions and metadata before and after change.

03

Test definers, grants, object status and dependency order in a scratch deployment.

04

Design reversible rollout/rollback steps instead of assuming DDL participates in application transactions.

05

Decide database-versus-application placement using consistency, latency, portability, observability and team-operability criteria.

Chapter integration

This lesson assumes the object semantics from Lessons 1–4. It does not turn mariadb-dump into a deployment system or backup into source control. The current Community baseline is 12.3.2; the public syllabus still references 11.8 LTS, so every production script must be tested against its exact target server series and topology.

1. Build a scratch deployment fixture

This lesson is independently runnable. Start from a disposable schema and create one representative view, procedure, function, trigger and disabled event. The definitions are deliberately small so deployment mechanics—not business complexity—remain visible.

sql · create representative stored objects for deployment testing
DROP DATABASE IF EXISTS servicehub_programmability_lab;CREATE DATABASE servicehub_programmability_lab;USE servicehub_programmability_lab;CREATE TABLE work_orders (  work_order_id BIGINT PRIMARY KEY,  status ENUM('open','closed') NOT NULL,  priority TINYINT NOT NULL,  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB;CREATE TABLE work_order_audit (  audit_id BIGINT AUTO_INCREMENT PRIMARY KEY,  work_order_id BIGINT NOT NULL,  old_status VARCHAR(20) NOT NULL,  new_status VARCHAR(20) NOT NULL,  changed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB;INSERT INTO work_orders VALUES(5001,'open',5,'2026-08-20 10:00:00'),(5002,'open',2,'2026-08-20 10:05:00');CREATE OR REPLACE ALGORITHM=MERGEDEFINER=CURRENT_USERSQL SECURITY INVOKERVIEW v_open_dispatch ASSELECT work_order_id,priority,updated_atFROM work_ordersWHERE status='open'WITH CASCADED CHECK OPTION;DELIMITER $$CREATE OR REPLACE PROCEDURE sp_close_work_order(IN p_id BIGINT)SQL SECURITY INVOKERMODIFIES SQL DATABEGIN  UPDATE work_orders  SET status='closed',updated_at=CURRENT_TIMESTAMP  WHERE work_order_id=p_id AND status='open';END$$CREATE OR REPLACE FUNCTION fn_priority_band(p_priority TINYINT)RETURNS VARCHAR(12)DETERMINISTICNO SQLSQL SECURITY INVOKERRETURN CASE WHEN p_priority >= 4 THEN 'high' ELSE 'normal' END$$CREATE OR REPLACE TRIGGER tr_wo_after_update_auditAFTER UPDATE ON work_ordersFOR EACH ROWBEGIN  IF NOT (OLD.status <=> NEW.status) THEN    INSERT INTO work_order_audit(work_order_id,old_status,new_status)    VALUES(NEW.work_order_id,OLD.status,NEW.status);  END IF;END$$DELIMITER ;CREATE OR REPLACEDEFINER=CURRENT_USEREVENT ev_expire_claimsON SCHEDULE EVERY 1 DAYDISABLEDO UPDATE work_orders   SET updated_at=CURRENT_TIMESTAMP WHERE status='open';

The event is intentionally DISABLEd: deployment tests should inspect and exercise dependencies manually before scheduled execution is permitted. Run this setup as a disposable lab administrator with the object-creation privileges required by your local Community Server.

2. Treat stored objects as a dependency graph

A database release has objects that depend on other objects and security identities. The exact order varies by schema, but a useful default is: establish controlled accounts/roles and base grants; deploy base tables; create routines that do not depend on later objects; create views; create triggers; create events disabled; run verification; then enable scheduled execution. If a view calls a function or an event calls a procedure, adjust the graph accordingly.

Object Common dependencies Pre-enable verification
View Tables/views/functions + definer/invoker privileges SHOW CREATE VIEW, select/write tests, IS_UPDATABLE/CHECK_OPTION
Procedure/function Tables/routines + CREATE/ALTER/EXECUTE security SHOW CREATE, success/error tests, transaction behavior
Trigger Table + called routines + TRIGGER/definer privileges SHOW CREATE, ACTION_ORDER, DML rollback tests
Event Called routines/tables + EVENT/definer privileges + scheduler ownership SHOW CREATE, STATUS/TIME_ZONE, manual procedure test, run-log evidence

Dependency order is not cosmetic. MariaDB can accept some definitions that later fail at execution when a referenced security identity or privilege is unavailable. The release gate must include execution tests, not only successful DDL.

3. Capture a pre-change evidence packet

Before changing server-side logic, record both definition and effective metadata. SHOW CREATE is the closest representation of what MariaDB stored, including definer/security clauses that a hand-written migration may omit. Information Schema provides fleet-friendly inventory queries.

sql · inventory stored objects and security identities
SELECT TABLE_NAME,ALGORITHM,IS_UPDATABLE,CHECK_OPTION,DEFINER,SECURITY_TYPEFROM information_schema.VIEWSWHERE TABLE_SCHEMA='servicehub_programmability_lab';SELECT ROUTINE_NAME,ROUTINE_TYPE,DATA_ACCESS,IS_DETERMINISTIC,SECURITY_TYPE,DEFINERFROM information_schema.ROUTINESWHERE ROUTINE_SCHEMA='servicehub_programmability_lab';SELECT TRIGGER_NAME,EVENT_OBJECT_TABLE,EVENT_MANIPULATION,ACTION_TIMING,ACTION_ORDER,DEFINERFROM information_schema.TRIGGERSWHERE TRIGGER_SCHEMA='servicehub_programmability_lab'ORDER BY EVENT_OBJECT_TABLE,EVENT_MANIPULATION,ACTION_TIMING,ACTION_ORDER;SELECT EVENT_NAME,DEFINER,TIME_ZONE,STATUS,LAST_EXECUTEDFROM information_schema.EVENTSWHERE EVENT_SCHEMA='servicehub_programmability_lab';
sql · capture exact definitions
SHOW CREATE VIEW servicehub_programmability_lab.v_open_dispatch\GSHOW CREATE PROCEDURE servicehub_programmability_lab.sp_close_work_order\GSHOW CREATE FUNCTION servicehub_programmability_lab.fn_priority_band\GSHOW CREATE TRIGGER servicehub_programmability_lab.tr_wo_after_update_audit\GSHOW CREATE EVENT servicehub_programmability_lab.ev_expire_claims\G

In a real release, store these outputs as review evidence or compare them to canonical SQL in source control. Normalize only nondeterministic formatting that your diff tooling understands; do not blindly delete DEFINER clauses from dumps because the security identity is material behavior.

4. Versioned deployment scripts need explicit ownership and rollback

One practical layout keeps each migration immutable and pairs forward change with a tested rollback or compensating migration. DDL is not an application transaction that you can always reverse with ROLLBACK. A rollback script must recreate the prior object definition and security attributes deliberately.

text · versioned deployment manifest for the mariadb client
-- deploy_release.sql-- Each SOURCE target is an immutable, reviewed file in the same release artifact.SOURCE 001_security_owner.sql;SOURCE 010_routines.sql;SOURCE 020_views.sql;SOURCE 030_triggers.sql;SOURCE 040_events_disabled.sql;SOURCE 090_verify.sql;SOURCE 100_enable.sql;
sql · 001_security_owner.sql — concrete ownership prerequisite
-- Run through a controlled deployment identity with CREATE USER/GRANT authority.CREATE USER IF NOT EXISTS 'svc_program_owner'@'localhost'  IDENTIFIED BY 'LabOnly-ChangeMe-42!';GRANT SELECT,INSERT,UPDATE,DELETE,EXECUTE,TRIGGER,EVENT  ON servicehub_programmability_lab.*  TO 'svc_program_owner'@'localhost';SHOW GRANTS FOR 'svc_program_owner'@'localhost';

The remaining numbered files contain the reviewed definitions exercised in this chapter: routines first, then dependent views/triggers, then events created disabled, verification, and finally a small enablement step. The manifest is intentionally explicit so a failed file stops the release at a known boundary. In production, inject credentials through your deployment secret mechanism instead of committing password material; the visible password above is only for this disposable local account.

Each numbered file is a reviewed deployment unit, not an ad-hoc paste. Production account creation should normally go through the organization’s privileged identity-management path. The local fixture exists only to make dependency, ownership and verification behavior observable.

sql · rollback is an explicit previous definition
-- Example principle, not a generic automatic rollback:ALTER EVENT servicehub_programmability_lab.ev_expire_claims DISABLE;-- Recreate the prior trigger/routine/view definitions from the release artifact.-- Re-run behavior tests before re-enabling jobs.-- Only remove a definer account after inventory proves no object depends on it.SELECT 'views' AS object_type,TABLE_NAME AS object_name,DEFINERFROM information_schema.VIEWSWHERE TABLE_SCHEMA='servicehub_programmability_lab'UNION ALLSELECT 'routine',ROUTINE_NAME,DEFINERFROM information_schema.ROUTINESWHERE ROUTINE_SCHEMA='servicehub_programmability_lab'UNION ALLSELECT 'trigger',TRIGGER_NAME,DEFINERFROM information_schema.TRIGGERSWHERE TRIGGER_SCHEMA='servicehub_programmability_lab'UNION ALLSELECT 'event',EVENT_NAME,DEFINERFROM information_schema.EVENTSWHERE EVENT_SCHEMA='servicehub_programmability_lab';

5. Deliberately wrong: use a dump as an unreviewed deployment artifact

mariadb-dump is valuable for logical backup/migration. Triggers are included by default unless disabled; procedures/functions and events require their corresponding options. A dump can also carry definers and environment-specific assumptions. Applying it blindly to another environment can create missing-owner failures or accidentally preserve an over-privileged owner.

shell · capture stored objects intentionally
# shell / PowerShell concept: run from a trusted client hostmariadb-dump --single-transaction --routines --events --triggers   --no-data servicehub_programmability_lab > servicehub_objects.sql# Review the artifact before restore/deployment.# Search specifically for DEFINER=, SQL SECURITY, CREATE TRIGGER and CREATE EVENT.

The wrong repair is a global text replacement such as “replace every DEFINER with root.” That can create privilege escalation and erase intentional INVOKER boundaries. The safer process inventories each stored object's owner, maps source owners to approved target owners, provisions least-privilege accounts first, and runs behavior tests after restore.

A backup is also not a deployment manifest. Backup tooling answers “can I restore the database state?” A release system answers “which reviewed change should be applied, in what order, with what owner, and how do I prove/undo it?” You need both.

6. Test privileges from the caller's perspective

Testing only as an administrator hides privilege bugs. Create or use a disposable application account with the intended grants, then verify both allowed and denied operations. For SQL SECURITY INVOKER, the caller needs underlying access. For DEFINER objects, the caller typically needs access to the stored interface while the definer owns the underlying privileges required by the body. Exact privilege requirements depend on object type and statement.

sql · privilege review checklist
SHOW GRANTS FOR CURRENT_USER;SHOW PRIVILEGES;-- For every dedicated definer account:SHOW GRANTS FOR 'svc_program_owner'@'localhost';-- Inventory definers again after deployment:SELECT TABLE_NAME AS object_name,DEFINER,SECURITY_TYPEFROM information_schema.VIEWSWHERE TABLE_SCHEMA='servicehub_programmability_lab';SELECT ROUTINE_NAME AS object_name,ROUTINE_TYPE,DEFINER,SECURITY_TYPEFROM information_schema.ROUTINESWHERE ROUTINE_SCHEMA='servicehub_programmability_lab';

Current MariaDB uses the SET USER privilege for assigning a different definer in relevant stored-object creation. Do not grant that capability broadly to application accounts. Keep deployment identities separate from runtime identities and record who is authorized to change stored security boundaries.

7. Decide whether the logic belongs in MariaDB or in the application

Criterion Database-side logic is attractive when… Application-side logic is attractive when…
Consistency The invariant must follow every SQL writer and stay in one transaction. Only one service owns writes and already enforces the invariant reliably.
Latency Avoiding extra client round trips materially simplifies an atomic operation. Logic needs external calls or long-running computation that should not hold DB resources.
Portability MariaDB-specific behavior is acceptable and tested. Cross-database portability is a product requirement.
Observability DB statement/lock/event evidence is integrated into operations. Application tracing/logging provides much richer causal context.
Deployment DB migrations and privilege review are mature and reversible. Application CI/CD is stronger and DB release ownership is weak.
Team operability DBAs/developers can read, test and support SQL/PSM. The team has little stored-program expertise and high bus-factor risk.

A practical boundary is often hybrid: table constraints for simple invariants, views for stable read interfaces, a few small procedures for atomic data-local workflows, triggers only for unavoidable writer-independent behavior, and external/application orchestration for distributed workflows. Do not move code into the database merely to reduce file count, and do not move every invariant into the application merely to avoid SQL/PSM.

8. Release acceptance matrix and production rollback triggers

Dimension Acceptance evidence Rollback / stop trigger
Definitions SHOW CREATE matches reviewed artifact. Unexpected definer, security mode, body or order.
Privileges Least-privilege caller tests pass; denied tests remain denied. Admin-only success or new unintended access.
Correctness Success/failure/transaction tests preserve business invariants. Partial state or hidden error swallowing.
Performance Representative DML/query/job latency remains within local SLO. Trigger/routine amplification causes lock or tail-latency regression.
Scheduling Events disabled during deploy, then one intended owner enabled. Duplicate/no owner or missing run evidence.
Topology Replication/Galera behavior tested for target deployment. Unverified trigger/event execution semantics.
Recovery Previous definitions and owner/grant state can be restored. Rollback artifact missing or depends on deleted account.

Monitoring signals include routine/trigger statement latency, lock waits, event run gaps/failures, error-log entries, deployment drift in SHOW CREATE, missing definers, privilege changes and replica/Galera symptoms. A server-side feature is production-ready only when the operational team knows where those signals live.

9. Chapter checkpoint, cleanup, and bridge to security

  1. Build an inventory of every Chapter 11 object: type, schema, name, definer, security mode, dependencies and owner.
  2. Capture canonical SHOW CREATE definitions.
  3. Run success and deliberate-failure tests as the intended caller, not only as admin.
  4. Keep events disabled until verification passes and scheduler ownership is clear.
  5. Test rollback by restoring the previous object definitions in a scratch schema.
  6. Remove disposable users and schemas only after the dependency inventory is empty.

Check your understanding

  1. Why is successful CREATE/ALTER DDL insufficient proof of a valid stored-object deployment?
  2. Why should events usually be enabled after, not before, verification?
  3. What is wrong with replacing every restored DEFINER with an administrator?
  4. What does SHOW CREATE contribute that a schema object list does not?
  5. Name two reasons to keep logic in the application instead of MariaDB.
Review the answers

DDL success does not prove the definer exists, privileges are sufficient, dependencies resolve, or runtime behavior is correct. Events are enabled last so scheduled execution cannot start before grants and dependencies are validated. Replacing every definer with an administrator can create privilege escalation and destroy intended INVOKER/least-privilege boundaries. SHOW CREATE captures the actual stored definition and security clauses. Application placement is often better for distributed/external workflows, richer tracing, portability, or teams without safe SQL/PSM operational ownership.

sql · cleanup only after the inventory is clear
-- In the disposable lab only:DROP DATABASE IF EXISTS servicehub_programmability_lab;DROP USER IF EXISTS 'svc_program_owner'@'localhost';

Chapter 11 established the first major server-side code/security boundary in the MariaDB course. Chapter 12 now deepens that boundary into accounts, roles, authentication, authorization and hardening: who can connect, which privileges they inherit, and how definers and stored objects fit into least-privilege server governance.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.