Εισαγωγή
Το merql είναι μια καθαρή βιβλιοθήκη PHP που εκτελεί συγχωνεύσεις τριών κατευθύνσεων σε καταστάσεις βάσεων δεδομένων. Δημιουργεί στιγμιότυπα πινάκων, υπολογίζει σύνολα αλλαγών μεταξύ στιγμιότυπων, συγχωνεύει δύο σύνολα αλλαγών βάσει μιας κοινής βάσης και εντοπίζει συγκρούσεις σε επίπεδο στήλης. Χρησιμοποιεί τον ίδιο αλγόριθμο που χρησιμοποιεί το git για αρχεία πηγαίου κώδικα, εφαρμοσμένο σε γραμμές και στήλες αντί για γραμμές κειμένου.
Χωρίς εξωτερικά εργαλεία. Υποστηρίζει τα MySQL και SQLite μέσω προσαρμόσιμων προσαρμογέων σύνδεσης και οδηγών διαλέκτου.
Γρήγορο παράδειγμα
Για μια συγχώνευση χρειάζονται τρεις καταστάσεις των ίδιων δεδομένων: η βάση από την οποία ξεκίνησαν και τα δύο αντίγραφα και τα δύο αντίγραφα αφού άλλαξαν ανεξάρτητα. Εδώ, ένα sandbox αντιγράφηκε από τη live βάση δεδομένων και έκτοτε έγιναν αλλαγές και στις δύο.
use Merql\Connection;
use Merql\Merql;
$live = Connection::sqlite('/data/live.sqlite');
$sandbox = Connection::sqlite('/data/sandbox.sqlite');
// Base: live at the moment the sandbox was copied from it.
Merql::init($live);
Merql::snapshot('base');
// ... copy live.sqlite to sandbox.sqlite, then both databases change ...
// Ours: the sandbox with our edits. Theirs: live with its own changes.
Merql::init($sandbox);
Merql::snapshot('ours');
Merql::init($live);
Merql::snapshot('theirs');
$result = Merql::merge('base', 'ours', 'theirs');
if ($result->isClean()) {
foreach ($result->operations() as $operation) {
echo "{$operation->type} {$operation->table} #{$operation->rowKey} ({$operation->source})\n";
}
} else {
echo "Conflicts: {$result->conflictCount()}\n";
}
Κάθε στιγμιότυπο λαμβάνεται από τη βάση δεδομένων που περιέχει αυτή την κατάσταση. Η διαδοχική λήψη και των τριών από μία βάση δεδομένων δεν περιγράφει δύο αποκλίνοντα αντίγραφα: το theirs θα περιείχε ήδη τις αλλαγές του ours και κάθε γραμμή που εισήγαγε το ours θα αναφερόταν ως σύγκρουση insert_insert.
Το αποτέλεσμα παραθέτει τις λειτουργίες που μετατρέπουν τη βάση στην κατάσταση συγχώνευσης, από τις δύο πλευρές, καθεμία με σημειωμένη την προέλευσή της (ours, theirs ή merged). Για να γράψετε τις αλλαγές του sandbox στη live βάση, εφαρμόστε τις λειτουργίες που λείπουν από τη live βάση με την Ελεγχόμενη εφαρμογή.
Ή από το CLI, το οποίο συνδέεται στη βάση δεδομένων που ονομάζεται στο MERQL_DB_DSN για κάθε snapshot:
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base
# ... copy live.sqlite to sandbox.sqlite, then both databases change ...
MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs
vendor/bin/merql merge base ours theirs --dry-run
Γιατί merql
Τα περισσότερα εργαλεία βάσεων δεδομένων που συγκρίνουν καταστάσεις λειτουργούν σε επίπεδο γραμμής: αν διαφέρει οποιαδήποτε στήλη μιας γραμμής ανάμεσα σε δύο εκδόσεις, ολόκληρη η γραμμή επισημαίνεται ως σύγκρουση. Έτσι προκύπτουν ψευδείς συγκρούσεις όταν δύο άτομα επεξεργάζονται διαφορετικές στήλες της ίδιας γραμμής.
Το merql συγχωνεύει σε επίπεδο στήλης. Αν η μία πλευρά άλλαξε το title και η άλλη το status, οι αλλαγές συγχωνεύονται ομαλά χωρίς σύγκρουση. Σύγκρουση προκύπτει μόνο όταν και οι δύο πλευρές αλλάξουν την ίδια στήλη σε διαφορετικές τιμές.
Για στήλες TEXT και JSON, το merql μπορεί να προχωρήσει ένα επίπεδο βαθύτερα με συγχώνευση σε επίπεδο κελιού. Δύο αλλαγές σε διαφορετικές γραμμές μιας στήλης κειμένου ή σε διαφορετικά κλειδιά μιας στήλης JSON μπορούν να συγχωνευθούν ομαλά με τον ίδιο αλγόριθμο τριών κατευθύνσεων. Η συγχώνευση σε επίπεδο κελιού είναι προαιρετική: μεταβιβάστε ένα CellMergeConfig στο ThreeWayMerge. Το facade Merql και το CLI συγχωνεύουν μόνο σε επίπεδο στήλης. Δείτε τη Συγχώνευση σε επίπεδο κελιού.
Το μοντέλο συγχώνευσης
Base (snapshot at fork time)
/ \
Ours (one copy's changes) Theirs (the other copy's changes)
\ /
--------- MERGE ----------
|
Merged result
+ conflicts (if any)
Τρεις καταστάσεις, όπως στο git. Η βάση είναι ο κοινός πρόγονος. Τα ours και theirs είναι τα δύο αντίγραφα αφού αποκλίνουν, καθένα καταγεγραμμένο από τη δική του βάση δεδομένων. Οι κανόνες συγχώνευσης αντιμετωπίζουν και τις δύο πλευρές ισότιμα. Τα ονόματα εμφανίζονται στο source κάθε λειτουργίας, στους τύπους σύγκρουσης (update_delete σημαίνει ότι το ours ενημερώθηκε και το theirs διαγράφηκε) και στις πολιτικές επίλυσης OursWins και TheirsWins. Χωρίς κοινή βάση, δεν μπορείτε να ξεχωρίσετε τι «προστέθηκε» από τι «παρέμεινε αμετάβλητο».
Μια συγχώνευση δεν γράφει τίποτα από μόνη της. Οι λειτουργίες της μετατρέπουν τη βάση στην κατάσταση συγχώνευσης, επομένως το Merql::apply() τις εκτελεί όλες ομαλά μόνο σε βάση δεδομένων που εξακολουθεί να περιέχει τη βάση. Για να μεταφέρετε τις αλλαγές της μίας πλευράς σε βάση δεδομένων που περιέχει ήδη τις αλλαγές της άλλης, όπως αλλαγές sandbox στη live βάση, εφαρμόστε μόνο τις λειτουργίες που της λείπουν· δείτε την Ελεγχόμενη εφαρμογή.
Απαιτήσεις
- PHP 8.2 ή νεότερη έκδοση.
ext-mbstringκαιext-zlib, που απαιτούνται από την εξάρτησηpitmaster/pitmasterη οποία παρέχει τη διαφορά κειμένου.- Επέκταση βάσης δεδομένων για τον προσαρμογέα που χρησιμοποιείτε:
ext-pdoμεext-pdo_sqliteήext-pdo_mysql, ήext-mysqli. Οιcomposer.jsonτου merql προτείνουν μόνο ταext-pdoκαιext-mysqli, επομένως το Composer δεν ελέγχει αν υπάρχουν. - Βάση δεδομένων MySQL ή SQLite. Για άλλες μηχανές χρειάζεται προσαρμοσμένος οδηγός.
Τι δεν είναι
Το merql δεν είναι εργαλείο μετεγκατάστασης σχήματος. Δεν αναπαράγει βάσεις δεδομένων ούτε τις συγχρονίζει σε πραγματικό χρόνο. Επιλύει ένα συγκεκριμένο πρόβλημα: δεδομένων τριών καταστάσεων βάσης δεδομένων, παράγει μια τέταρτη συγχωνευμένη κατάσταση με εντοπισμένες συγκρούσεις.
Τεκμηρίωση
- Ξεκινώντας -- εγκατάσταση, πρώτο στιγμιότυπο, πρώτη συγχώνευση.
- Αναφορά CLI -- πλήρης αναφορά για την εντολή
vendor/bin/merql. - Αναφορά PHP API -- πλήρης τεκμηρίωση API για όλες τις κλάσεις.
- Σχέδια συγχώνευσης -- σταθερά αναγνωριστικά λειτουργιών, ομάδες αλλαγών και επιλογές.
- Ελεγχόμενη εφαρμογή -- επιλεγμένες εγγραφές με προϋποθέσεις για τις ενεργές γραμμές.
- Αναίρεση -- τεχνουργήματα αναίρεσης και έλεγχοι αποκλίσεων.