Μεταναστεύσεις δεδομένων — DedSec Project
Μεταναστεύσεις βάσεων — ελεγμένες εκδόσεις και επαναλήψιμες αλλαγές Συμβόλαιο σχήματος Μία εφαρμογή χωρίς διαδίκτυο έχει πίνακα εργασιών με κωδικό και τίτλο στην έκδοση 1. Στην έκδοση 2…
Μεταναστεύσεις βάσεων — ελεγμένες εκδόσεις και επαναλήψιμες αλλαγές
Συμβόλαιο σχήματος
Μία εφαρμογή χωρίς διαδίκτυο έχει πίνακα εργασιών με κωδικό και τίτλο στην έκδοση 1. Στην έκδοση 2 προστίθεται πεδίο done, με τιμές 0 ή 1 και αρχική τιμή 0 για τις παλιές εγγραφές. Η μεταβολή πρέπει να διατηρεί τα δεδομένα, να ενημερώνει την έκδοση μόνο μετά από επιτυχία και να αντέχει δεύτερη κλήση χωρίς να ξαναπροσθέτει τη στήλη. Άγνωστες εκδόσεις απορρίπτονται, δεν θεωρούνται αυτόματα συμβατές.
Εκτελέσιμο παράδειγμα SQLite/Python 3
Αποθήκευσε ως migration_lab.py και εκτέλεσε python3 migration_lab.py. Η βάση είναι προσωρινή στη μνήμη. Το PRAGMA user_version κρατά την έκδοση του σχήματος, ενώ τα BEGIN, commit και rollback προστατεύουν τόσο την αλλαγή πίνακα όσο και την ενημέρωση έκδοσης.
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE tasks(id INTEGER PRIMARY KEY,title TEXT NOT NULL)")
db.execute("INSERT INTO tasks(title) VALUES ('one')")
db.commit()
db.execute("PRAGMA user_version=1")
def migrate():
version = db.execute("PRAGMA user_version").fetchone()[0]
if version == 2:
return
if version != 1:
raise ValueError("unknown schema version")
db.execute("BEGIN")
try:
db.execute("""ALTER TABLE tasks ADD COLUMN done INTEGER
NOT NULL DEFAULT 0 CHECK(done IN (0,1))""")
db.execute("PRAGMA user_version=2")
db.commit()
except Exception:
db.rollback()
raise
migrate()
migrate()
assert db.execute("PRAGMA user_version").fetchone()[0] == 2
assert db.execute("SELECT done FROM tasks").fetchone()[0] == 0
print("PASS: versioned and repeatable migration")
Όρια αξιοπιστίας
Η δεύτερη κλήση βρίσκει έκδοση 2 και ολοκληρώνεται χωρίς να επιχειρήσει ξανά ALTER TABLE. Η προεπιλογή NOT NULL DEFAULT 0 συμπληρώνει το νέο πεδίο στις υπάρχουσες εγγραφές. Αν αποθηκεύσεις την έκδοση χωριστά από την αλλαγή σχήματος, μία διακοπή μπορεί να δημιουργήσει ασυνέπεια: τα μεταδεδομένα λένε 2 αλλά η στήλη δεν υπάρχει. Η SQLite υποστηρίζει ατομική αλλαγή σχήματος στο συγκεκριμένο παράδειγμα· άλλες μηχανές βάσεων μπορεί να έχουν διαφορετική συμπεριφορά. Για πραγματική αναβάθμιση χρειάζονται αντίγραφο ασφαλείας και δοκιμές όλων των υποστηριζόμενων παλιών εκδόσεων.
Ασκήσεις αποτυχίας και επαναφοράς
- Αφαίρεσε τον έλεγχο έκδοσης και εκτέλεσε δύο φορές την ALTER TABLE. Κατάγραψε το σφάλμα διπλής στήλης και μετά επανάφερε τον έλεγχο.
- Όρισε user_version=99 και επιβεβαίωσε ότι η διαδικασία δεν εφευρίσκει διαδρομή αναβάθμισης.
- Βάλε άκυρη εντολή SQL πριν την ενημέρωση έκδοσης και βεβαιώσου ότι γίνεται rollback και μένει το αρχικό σχήμα.
- Πρόσθεσε τρίτη έκδοση, δοκίμασε 1→2→3 σε προσωρινή βάση αρχείου και κλείσε/άνοιξε την ξανά για να επαληθεύσεις τη διατήρηση.
Παραδοτέα: PASS, σχήμα πριν και μετά, απορριπτέα άγνωστη έκδοση και καταγεγραμμένη διαδικασία αντιγράφου ασφαλείας και ανάκαμψης.