sstablescrub
Offline utility to repair corrupted SSTables by removing damaged data while preserving valid rows.
Synopsis
Section titled “Synopsis”sstablescrub [options] <keyspace> <table>Description
Section titled “Description”sstablescrub is the offline equivalent of nodetool scrub. It scans SSTable files, identifies corrupted or malformed data, and rewrites the SSTables with only valid data. This tool can fix corruption that nodetool scrub cannot handle because it operates without Cassandra's runtime constraints.
Cassandra Must Be Stopped
Cassandra must be completely stopped before running sstablescrub. Running this tool while Cassandra is active will cause data corruption and unpredictable behavior.
How It Works
Section titled “How It Works”What Scrubbing Does
Section titled “What Scrubbing Does”- Reads each row from the SSTable sequentially
- Validates row structure - checks for malformed data
- Validates data types - ensures values match schema (unless
--no-validate) - Skips corrupted rows - drops rows that cannot be read
- Writes valid rows to new SSTable
- Handles counters - special processing for counter tables
- Updates metadata - new SSTables are marked as unrepaired
Arguments
Section titled “Arguments”| Argument | Description |
|---|---|
keyspace | Name of the keyspace containing the table |
table | Name of the table to scrub |
Options
Section titled “Options”| Option | Description |
|---|---|
-m, --manifest-check | Only check and repair the leveled manifest (LCS tables) |
-n, --no-validate | Skip validation of data values; only check structure |
-r, --reinsert-overflowed-ttl | Rewrite rows with TTL overflow (TTL > max allowed) |
-s, --skip-corrupted | Skip scrubbing counter tables if corruption prevents completion |
-e, --header-fix <mode> | Handle serialization header issues (see modes below) |
-v, --verbose | Enable verbose output |
-h, --help | Display help information |
--debug | Enable debug output |
Header Fix Modes (-e)
Section titled “Header Fix Modes (-e)”Deprecated Option
The --header-fix option is deprecated and no longer functional in recent Cassandra versions. It only emits a warning and has no effect on scrubbing behavior.
| Mode | Behavior |
|---|---|
validate | (Default) Validate header, error if mismatch found |
validate-only | Only validate header, do not attempt fixes |
fix | Validate header, fix issues if possible, then scrub |
fix-only | Only fix header issues, don't scrub data |
off | Disable header validation entirely |
Examples
Section titled “Examples”Basic Scrub
Section titled “Basic Scrub”# Stop Cassandra firstsudo systemctl stop cassandra
# Scrub a tablesstablescrub my_keyspace my_table
# Start Cassandrasudo systemctl start cassandraScrub Without Data Validation
Section titled “Scrub Without Data Validation”# Skip value validation - useful when schema has changed# but data is structurally soundsstablescrub --no-validate my_keyspace my_tableHandle Counter Table Corruption
Section titled “Handle Counter Table Corruption”# If counter corruption prevents normal scrubsstablescrub --skip-corrupted my_keyspace counter_tableFix TTL Overflow Issues
Section titled “Fix TTL Overflow Issues”# Rewrite rows where TTL exceeded maximum valuesstablescrub --reinsert-overflowed-ttl my_keyspace my_tableFix Serialization Header Issues
Section titled “Fix Serialization Header Issues”# Fix UDT (User Defined Type) serialization header problemssstablescrub -e fix my_keyspace my_table
# Only fix header, don't scrub datasstablescrub -e fix-only my_keyspace my_tableLCS Manifest Check Only
Section titled “LCS Manifest Check Only”# Only check and repair the LCS leveled manifestsstablescrub --manifest-check my_keyspace my_tableDebug Mode
Section titled “Debug Mode”# Enable verbose debug outputsstablescrub --debug my_keyspace my_tableWhen to Use sstablescrub
Section titled “When to Use sstablescrub”Scenario 1: Cassandra Won't Start Due to Corruption
Section titled “Scenario 1: Cassandra Won't Start Due to Corruption”# Symptom: Cassandra fails to start with SSTable errors in logs# Error: "Corrupt sstable" or "Cannot read sstable"
# 1. Identify the corrupted table from logsgrep -i "corrupt" /var/log/cassandra/system.log
# 2. Ensure Cassandra is stoppedsudo systemctl stop cassandrapgrep -f CassandraDaemon # Should return nothing
# 3. Scrub the affected tablesstablescrub my_keyspace corrupted_table
# 4. Start Cassandrasudo systemctl start cassandra
# 5. Repair to restore consistency (data was dropped)nodetool repair my_keyspace corrupted_tableScenario 2: nodetool scrub Fails
Section titled “Scenario 2: nodetool scrub Fails”# When nodetool scrub cannot complete due to severe corruption# Error: "Scrub failed" or out of memory errors
# 1. Stop Cassandrasudo systemctl stop cassandra
# 2. Try offline scrub with skip-corruptedsstablescrub --skip-corrupted my_keyspace my_table
# 3. If that fails, try without validationsstablescrub --no-validate --skip-corrupted my_keyspace my_table
# 4. Start Cassandra and repairsudo systemctl start cassandranodetool repair my_keyspace my_tableScenario 3: Schema Change Caused Data Issues
Section titled “Scenario 3: Schema Change Caused Data Issues”# After schema changes, data may not validate against new schema
# Scrub without validation to preserve datasstablescrub --no-validate my_keyspace my_tableScenario 4: Counter Table Issues
Section titled “Scenario 4: Counter Table Issues”# Counter tables require special handlingsstablescrub --skip-corrupted my_keyspace counter_tableScenario 5: UDT (User Defined Type) Header Mismatch
Section titled “Scenario 5: UDT (User Defined Type) Header Mismatch”# When frozen/non-frozen UDT serialization doesn't match schemasstablescrub -e fix my_keyspace my_tableImpact and Side Effects
Section titled “Impact and Side Effects”What Changes After Scrubbing
Section titled “What Changes After Scrubbing”| Aspect | Before | After |
|---|---|---|
| Corrupted rows | Present but unreadable | Removed permanently |
| SSTable count | Original count | May change (rewritten) |
| Repair status | Original state | Marked unrepaired |
| Disk space | Original | Temporary increase during operation |
| Data consistency | Inconsistent | Consistent locally, needs repair cluster-wide |
Data Loss
Scrubbing permanently removes corrupted rows. This data is lost unless:
- It exists on other replicas (run repair to recover)
- A backup exists with the data
- The original SSTable is preserved
Repair Status Change
Section titled “Repair Status Change”Scrubbed SSTables are marked as unrepaired. This affects incremental repair:
# After scrub, check repair statussstablemetadata /var/lib/cassandra/data/my_keyspace/my_table-*/nb-*-big-Data.db | grep -i repair
# Run repair to mark as repaired and restore consistencynodetool repair my_keyspace my_tablePre-Scrub Checklist
Section titled “Pre-Scrub Checklist”#!/bin/bashKEYSPACE="$1"TABLE="$2"
echo "=== Pre-Scrub Safety Check ==="
# 1. Verify Cassandra is stoppedecho ""echo "1. Checking Cassandra status..."if pgrep -f CassandraDaemon > /dev/null; then echo "ERROR: Cassandra is running! Stop it first." echo "Run: sudo systemctl stop cassandra" exit 1else echo "OK: Cassandra is stopped"fi
# 2. Check disk spaceecho ""echo "2. Checking disk space..."DATA_DIR="/var/lib/cassandra/data"USED=$(df ${DATA_DIR} | tail -1 | awk '{print $5}' | tr -d '%')if [ ${USED} -gt 80 ]; then echo "WARNING: Disk ${USED}% full. Scrub needs temporary space."else echo "OK: Disk usage at ${USED}%"fi
# 3. Count SSTablesecho ""echo "3. SSTable count:"SSTABLE_COUNT=$(find ${DATA_DIR}/${KEYSPACE}/${TABLE}-*/ -name "*Data.db" 2>/dev/null | wc -l)echo " Found ${SSTABLE_COUNT} SSTables"
# 4. Calculate data sizeecho ""echo "4. Data size:"du -sh ${DATA_DIR}/${KEYSPACE}/${TABLE}-*/ 2>/dev/null
# 5. Recommend snapshotecho ""echo "5. RECOMMENDATION:"echo " Before scrubbing, create a backup:"echo " cp -r ${DATA_DIR}/${KEYSPACE}/${TABLE}-*/ /backup/before_scrub/"
echo ""echo "=== Ready to scrub ==="echo "Command: sstablescrub ${KEYSPACE} ${TABLE}"Post-Scrub Actions
Section titled “Post-Scrub Actions”1. Check Results
Section titled “1. Check Results”# Check for dropped rows in output# sstablescrub outputs statistics about what was processed
# Verify SSTable countfind /var/lib/cassandra/data/my_keyspace/my_table-*/ -name "*Data.db" | wc -l2. Start Cassandra
Section titled “2. Start Cassandra”sudo systemctl start cassandra
# Wait for node to be fully upsleep 30nodetool status3. Run Repair
Section titled “3. Run Repair”# Critical: restore consistency from other replicasnodetool repair my_keyspace my_table
# For incremental repairnodetool repair -pr my_keyspace my_table4. Verify Data
Section titled “4. Verify Data”# Sample query to verify table is accessiblecqlsh -e "SELECT * FROM my_keyspace.my_table LIMIT 10;"
# Check for expected row count (compare to before)cqlsh -e "SELECT COUNT(*) FROM my_keyspace.my_table;"Troubleshooting
Section titled “Troubleshooting”Scrub Hangs or Takes Too Long
Section titled “Scrub Hangs or Takes Too Long”# Check progress (run in another terminal)ls -la /var/lib/cassandra/data/my_keyspace/my_table-*/
# Increase JVM heap if out of memoryexport JVM_OPTS="-Xmx8G"sstablescrub my_keyspace my_table"Unable to read sstable" Error
Section titled “"Unable to read sstable" Error”# Try with skip-corruptedsstablescrub --skip-corrupted my_keyspace my_table
# If still fails, SSTable may be too damaged# Consider removing the specific SSTable and repairingCounter Shard Errors
Section titled “Counter Shard Errors”# Counter tables need special handlingsstablescrub --skip-corrupted my_keyspace counter_table
# After scrub, repair is critical for counter consistencynodetool repair my_keyspace counter_tablePermission Denied
Section titled “Permission Denied”# Run as cassandra usersudo -u cassandra sstablescrub my_keyspace my_table
# Or fix ownershipsudo chown -R cassandra:cassandra /var/lib/cassandra/data/Out of Disk Space
Section titled “Out of Disk Space”# Scrub creates new SSTables before removing old ones# Need approximately 2x the table size temporarily
# Check spacedf -h /var/lib/cassandra
# Options:# 1. Free up space first# 2. Scrub tables one at a time# 3. Move data directory temporarilysstablescrub vs nodetool scrub
Section titled “sstablescrub vs nodetool scrub”| Aspect | sstablescrub | nodetool scrub |
|---|---|---|
| Cassandra state | Must be stopped | Must be running |
| Corruption level | Can handle severe | Limited by runtime |
| Performance impact | None (offline) | Consumes resources |
| Concurrency | Sequential | Can be concurrent |
| When to use | Cassandra won't start | Routine maintenance |
| Counter handling | --skip-corrupted | Limited |
| Header fixes | -e fix option | Not available |
Best Practices
Section titled “Best Practices”sstablescrub Guidelines
- Always backup first - Snapshot or copy SSTables before scrubbing
- Stop Cassandra - Never run while Cassandra is active
- Check disk space - Need ~2x table size temporarily
- Run repair after - Restore consistency from other replicas
- Use --no-validate carefully - May preserve problematic data
- Monitor output - Check how many rows were dropped
- Test in staging - Validate procedure before production
Cautions
- Corrupted rows are permanently removed
- SSTables become unrepaired after scrubbing
- Counter tables need special handling
- Large tables take significant time to scrub
Related Commands
Section titled “Related Commands”| Command | Relationship |
|---|---|
| nodetool scrub | Online version (less powerful) |
| sstableverify | Check integrity without modifying |
| nodetool repair | Restore consistency after scrub |
| sstablerepairedset | Manage repair status |
| sstablemetadata | Check SSTable properties |