Skip to main content

Delete tenant-scoped MySQL data by walking foreign-key relationships

Project description

Titto

Titto deletes tenant-scoped rows from a MySQL schema by reading table metadata, following foreign-key paths back to a tenant table, nulling optional references, and deleting rows in dependency order.

Warnings

This is a destructive database tool. Run it against production only after testing the exact command against a restored copy or staging database.

--commit permanently commits the deletes. Without --commit, Titto still runs the UPDATE and DELETE statements inside a transaction, then rolls them back. That dry run can still take locks, fire triggers, and affect non-transactional tables.

Take a backup before any committed run. Prefer a database snapshot or logical dump that you have already tested restoring. Keep the backup until the tenant removal has been verified.

Usage

Show commands:

uv run titto --help

Dry-run a single-column tenant key and cache table metadata as JSON:

uv run titto delete "$DB_URL" tenant 42 --cache .tables.json

Commit the delete:

uv run titto delete "$DB_URL" tenant 42 --cache .tables.json --commit

Use a composite tenant key by passing each primary-key part as its own token:

uv run titto delete "$DB_URL" tenant 42 eu --cache .tables.json

Require selected tables to be empty for the tenant before deleting anything:

uv run titto delete "$DB_URL" tenant 42 --skip invoice --skip payment

Clean up unreferenced rows in tables that are not directly tenant-scoped:

uv run titto cleanup "$DB_URL" tenant --cache .tables.json

The automatic cleanup selection also skips tables with a UNIQUE constraint.

Clean up unreferenced rows in explicitly selected tables:

uv run titto cleanup-tables "$DB_URL" tag category --cache .tables.json

Find rows whose outgoing foreign keys resolve to different tenants:

uv run titto check-cross-tenant "$DB_URL" tenant --limit 100 --cache .tables.json

For each table, Titto finds outgoing foreign keys that point to tenant-scoped tables, then compares the first candidate with each later candidate. Each referenced table is resolved through its shortest foreign-key path to the tenant table. The limit is applied per table. By default, results are human-readable and progress logs are hidden. Use --json to print one JSON object per mismatch, and --verbose to show progress logs on stderr.

DB_URL is a MySQL URL such as:

mysql://user:password@localhost:3306/app_schema

Avoid putting real passwords directly in shell history. Use an environment variable, secret manager, or another shell-safe mechanism appropriate for your environment.

Cache Notes

--cache stores parsed table metadata as JSON. The recommended local cache path is .tables.json; it is ignored by Git.

The cache is tied to the host, port, schema name, and cache format version. Titto rejects mismatched cache metadata and reparses the database schema. If the schema changes on the same host and schema name, delete .tables.json so Titto can refresh it.

Development

Run the test suite:

uv run python -m unittest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

titto-0.4.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

titto-0.4.0-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file titto-0.4.0.tar.gz.

File metadata

  • Download URL: titto-0.4.0.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Alpine Linux","version":"3.23.4","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for titto-0.4.0.tar.gz
Algorithm Hash digest
SHA256 496b121437df4cd331a683161d8f357f4095dd6e9ad51f3adeabe09aea2bb02e
MD5 38323daf50ba49df488a3a96d7de59b7
BLAKE2b-256 2ade7e2e84519be13522805d4318b2b6e57ce0e9aba3cda1578b98710cf05dbf

See more details on using hashes here.

File details

Details for the file titto-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: titto-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Alpine Linux","version":"3.23.4","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for titto-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bb9a03ff62287f639e0369323709a3b9ac09857c101208bb3d2150bb26b6da9b
MD5 8e953a5676f2383312c00b03cc1edbc6
BLAKE2b-256 87e7f37425afe9447840450be439f90cf700b866dc1cdfa716eefce6a3f74d1c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page