Μετάβαση στο περιεχόμενο

Ταυτότητα γραμμής

Η ταυτότητα γραμμής καθορίζει τον τρόπο με τον οποίο το merql αντιστοιχίζει γραμμές μεταξύ στιγμιότυπων. Κατά τη σύγκριση της βάσης με τη δική μας έκδοση, πρέπει να γνωρίζει ότι η γραμμή X στη βάση είναι η ίδια λογική γραμμή με τη γραμμή Y στη δική μας, ακόμη κι αν έχουν αλλάξει ορισμένες τιμές στηλών. Ο κανόνας ταυτότητας καθορίζει ποιες στήλες σχηματίζουν το κλειδί της γραμμής.

PHP
use Merql\Identity\PrimaryKeyIdentity;

$identity = new PrimaryKeyIdentity(['id']);
$key = $identity->key(['id' => 42, 'title' => 'Hello']);
// "42"

Η διεπαφή RowIdentity

Όλες οι στρατηγικές ταυτότητας υλοποιούν δύο μεθόδους:

PHP
interface RowIdentity
{
    public function key(array $row): string;
    public function columns(): array;
}

Η key() δημιουργεί ένα μοναδικό αναγνωριστικό συμβολοσειράς από τα δεδομένα μιας γραμμής. Η columns() επιστρέφει τα ονόματα των στηλών που χρησιμοποιούνται για την ταυτότητα.

PrimaryKeyIdentity

Η προεπιλεγμένη στρατηγική. Αντιστοιχίζει γραμμές με βάση τις στήλες του πρωτεύοντος κλειδιού τους.

PHP
use Merql\Identity\PrimaryKeyIdentity;

// Single-column PK.
$identity = new PrimaryKeyIdentity(['id']);
$key = $identity->key(['id' => 42, 'title' => 'Hello']);
// "42"

// Composite PK.
$identity = new PrimaryKeyIdentity(['tenant_id', 'user_id']);
$key = $identity->key(['tenant_id' => 1, 'user_id' => 99, 'name' => 'Alice']);
// "1\x1F99" (unit separator between parts)

Αυτή είναι η προεπιλογή του merql όταν ο πίνακας έχει πρωτεύον κλειδί ορισμένο στο σχήμα του.

NaturalKeyIdentity

Για πίνακες χωρίς πρωτεύον κλειδί αυτόματης αύξησης, αντιστοιχίζει γραμμές με βάση τις στήλες μοναδικών περιορισμών. Χρήσιμο όταν το PK είναι UUID ή όταν ο πίνακας χρησιμοποιεί σύνθετο μοναδικό περιορισμό ως λογική ταυτότητα.

PHP
use Merql\Identity\NaturalKeyIdentity;

$identity = new NaturalKeyIdentity(['email']);
$key = $identity->key(['id' => 1, 'email' => 'alice@example.com', 'name' => 'Alice']);
// "alice@example.com"

$identity = new NaturalKeyIdentity(['country', 'postal_code']);
$key = $identity->key(['country' => 'US', 'postal_code' => '90210', 'city' => 'Beverly Hills']);
// "US\x1F90210"

ContentHashIdentity

Εναλλακτική λύση για πίνακες χωρίς πρωτεύον κλειδί και χωρίς μοναδικούς περιορισμούς. Υπολογίζει έναν κατακερματισμό SHA-256 όλων των τιμών των στηλών. Δύο γραμμές θεωρούνται ίδιες αν όλες οι στήλες τους ταιριάζουν.

PHP
use Merql\Identity\ContentHashIdentity;

$identity = new ContentHashIdentity(['name', 'value']);
$key = $identity->key(['name' => 'color', 'value' => 'blue']);
// "a3f2..." (SHA-256 hash)

Η ταυτότητα μέσω κατακερματισμού περιεχομένου έχει έναν περιορισμό: αν αλλάξει το περιεχόμενο μιας γραμμής, αλλάζει και ο κατακερματισμός της, οπότε η γραμμή εμφανίζεται ως διαγραφή του παλιού κατακερματισμού και εισαγωγή του νέου, αντί ως ενημέρωση. Αυτός είναι ένας εγγενής συμβιβασμός όταν δεν υπάρχουν σταθερές στήλες ταυτότητας.

IdentityRule

Το IdentityRule είναι η σειριοποιήσιμη διαμόρφωση ταυτότητας που χρησιμοποιείται από τη λήψη στιγμιότυπων και τα σχέδια συγχώνευσης.

PHP
use Merql\Identity\IdentityRule;

$rule = IdentityRule::natural(['option_name']);
$key = $rule->key(['option_name' => 'siteurl']);
// "siteurl"

Τύποι κανόνων:

Τύπος Σημασία
primary Στήλες πρωτεύοντος κλειδιού βάσης δεδομένων
natural Σταθερές μοναδικές επιχειρησιακές στήλες
composite Σύνθετες στήλες λογικής ταυτότητας
content Εφεδρικός κατακερματισμός περιεχομένου

Το IdentityRule::forSchema($schema) επιλύει τον προεπιλεγμένο κανόνα:

  1. Αν ο πίνακας έχει πρωτεύον κλειδί, χρησιμοποιούνται οι στήλες του.
  2. Αν ο πίνακας έχει μοναδικά κλειδιά, χρησιμοποιούνται οι στήλες του πρώτου μοναδικού κλειδιού.
  3. Αν δεν ισχύει τίποτα από τα δύο, χρησιμοποιούνται όλες οι στήλες (εφεδρική λύση με κατακερματισμό περιεχομένου).

IdentityRuleSet

Χρησιμοποιήστε το IdentityRuleSet όταν η εφαρμογή υποδοχής γνωρίζει έναν καλύτερο κανόνα ταυτοποίησης από τον προεπιλεγμένο κανόνα του σχήματος.

PHP
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;
use Merql\Snapshot\Snapshotter;

$rules = new IdentityRuleSet([
    'wp_options' => IdentityRule::natural(['option_name']),
    'wp_term_relationships' => IdentityRule::composite(['object_id', 'term_taxonomy_id']),
]);

$snapshotter = new Snapshotter($connection, identityRules: $rules);
$snapshot = $snapshotter->capture('live', ['wp_options', 'wp_term_relationships']);

Το Snapshotter επιλύει ένα IdentityRule για κάθε πίνακα που καταγράφεται. Οι επιλεγμένες στήλες αποθηκεύονται στο TableSnapshot::identityColumns και χρησιμοποιούνται σε όλες τις επόμενες λειτουργίες diff, merge, plan, SQL και rollback.

Το Merql::init() μπορεί να λάβει το ίδιο σύνολο κανόνων κατά τη χρήση της στατικής πρόσοψης:

PHP
use Merql\Merql;

Merql::init($connection, identityRules: $rules);
Merql::snapshot('live', ['wp_options']);

Τα σύνολα κανόνων έχουν σταθερή σειριοποίηση πίνακα:

PHP
$payload = $rules->toArray();
$rules = IdentityRuleSet::fromArray($payload);

Αμφίσημη ταυτοποίηση

Αν δύο καταγεγραμμένες γραμμές παράγουν το ίδιο κλειδί ταυτοποίησης, η καταγραφή αποτυγχάνει αντί να αντικαταστήσει τη μία γραμμή με την άλλη.

PHP
use Merql\Exceptions\SnapshotException;

try {
    $snapshotter->capture('live', ['wp_postmeta']);
} catch (SnapshotException $e) {
    // The configured identity rule matched multiple rows.
}

Οι εφαρμογές υποδοχής μπορούν να ελέγξουν εκ των προτέρων τις ακατέργαστες γραμμές με το IdentityRuleSet::conflictsFor() όταν θέλουν να αναφέρουν την ασάφεια πριν από την καταγραφή:

PHP
$conflicts = $rules->conflictsFor(
    'wp_postmeta',
    IdentityRule::natural(['post_id', 'meta_key']),
    $rows,
);

Για πίνακες meta του WordPress, το post_id + meta_key είναι συνήθως χρήσιμο για ομαδοποίηση και εμφάνιση, αλλά δεν είναι ασφαλές ως ταυτότητα γραμμής, επειδή επιτρέπονται διπλά κλειδιά meta. Χρησιμοποιήστε το πρωτεύον κλειδί του πίνακα για την ταυτότητα γραμμής, εκτός αν η εφαρμογή υποδοχής μπορεί να αποδείξει ότι το φυσικό κλειδί είναι μοναδικό.

Κωδικοποίηση κλειδιού γραμμής

Τα κλειδιά γραμμών είναι κωδικοποιημένες συμβολοσειρές που συνδυάζουν τιμές πολλών στηλών με ένα διαχωριστικό μονάδας (\x1F). Οι τιμές που περιέχουν το διαχωριστικό ή το σύμβολο ποσοστού διαφεύγονται για την αποφυγή συγκρούσεων:

PHP
use Merql\Snapshot\Snapshotter;

// Encode.
$key = Snapshotter::buildRowKey(
    ['tenant_id' => '1', 'user_id' => '99'],
    ['tenant_id', 'user_id'],
);
// "1\x1F99"

// Decode.
$parts = Snapshotter::decodeRowKey($key);
// ['1', '99']

Κανόνες διαφυγής:

Αρχικό Με διαφυγή
% %25
\x1F (διαχωριστικό μονάδας) %1F

Έτσι διασφαλίζεται ότι μια τιμή που περιέχει \x1F δεν διασπάται σε πολλά μέρη κλειδιού. Η κωδικοποίηση είναι ντετερμινιστική και αντιστρέψιμη.

Απόκλιση αυτόματης αύξησης

Όταν και οι δύο πλευρές εισάγουν νέες γραμμές, τα ID αυτόματης αύξησης διαφέρουν μεταξύ των κλάδων. Η γραμμή #100 στη δική μας πλευρά μπορεί να είναι εντελώς διαφορετική εγγραφή από τη γραμμή #100 στη δική τους.

Το merql το χειρίζεται αυτό αντιστοιχίζοντας βάσει πρωτεύοντος κλειδιού. Αν και οι δύο πλευρές εισήγαγαν γραμμή με το ίδιο ID αυτόματης αύξησης, επισημαίνεται ως διένεξη insert_insert. Για να το αποφύγετε, χρησιμοποιήστε φυσικά κλειδιά (μοναδικές στήλες που παραμένουν σταθερές μεταξύ κλάδων) σε πίνακες όπου αναμένονται ταυτόχρονες εισαγωγές.

PHP
// A natural key on (slug) avoids auto-increment collisions.
$identity = new NaturalKeyIdentity(['slug']);

Ταυτοποίηση σε στιγμιότυπα

Οι στήλες ταυτοποίησης που επιλέγονται κατά την καταγραφή αποθηκεύονται με κάθε TableSnapshot:

PHP
$tableSnapshot = $snapshot->getTable('posts');
$tableSnapshot->identityColumns;
// ['id']

Αυτές οι στήλες χρησιμοποιούνται από το SqlGenerator για τη δημιουργία όρων WHERE σε εντολές UPDATE και DELETE, καθώς και από τα σχέδια συγχώνευσης για την εμφάνιση αποκωδικοποιημένων τιμών ταυτοποίησης προς έλεγχο, επιλογή, guarded apply και rollback.