Preskoči na vsebino

Identiteta vrstice

Identiteta vrstice določa, kako merql povezuje vrstice med posnetki. Pri primerjavi osnovne različice z našo mora vedeti, da je vrstica X v osnovni različici ista logična vrstica kot vrstica Y v naši, tudi če so se nekatere vrednosti stolpcev spremenile. Pravilo identitete določa, kateri stolpci sestavljajo ključ vrstice.

PHP
use Merql\Identity\PrimaryKeyIdentity;

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

Vmesnik RowIdentity

Vse strategije identitete implementirajo dve metodi:

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

key() iz podatkov vrstice izdela enolični identifikator v obliki niza. columns() vrne imena stolpcev, uporabljenih za identifikacijo.

PrimaryKeyIdentity

Privzeta strategija. Poveže vrstice glede na njihove stolpce primarnega ključa.

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)

To je privzeta strategija, ki jo uporablja merql, kadar ima tabela v shemi določen primarni ključ.

NaturalKeyIdentity

Pri tabelah brez primarnega ključa s samodejnim povečevanjem poveže vrstice glede na stolpce omejitve enoličnosti. Uporabno, kadar je PK UUID ali kadar tabela kot logično identiteto uporablja sestavljeno omejitev enoličnosti.

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

Rezervna možnost za tabele brez primarnega ključa in omejitev enoličnosti. Izračuna zgoščeno vrednost SHA-256 vseh vrednosti stolpcev. Vrstici sta enaki, če se ujemajo vsi stolpci.

PHP
use Merql\Identity\ContentHashIdentity;

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

Identifikacija z zgoščeno vrednostjo vsebine ima omejitev: če se vsebina vrstice spremeni, se spremeni tudi njena zgoščena vrednost, zato je vrstica prikazana kot izbris stare zgoščene vrednosti in vstavljanje nove, namesto kot posodobitev. To je neizogiben kompromis, kadar ni stabilnih stolpcev identitete.

IdentityRule

IdentityRule je serializabilna konfiguracija identitete, ki jo uporabljata zajem posnetka in načrti združevanja.

PHP
use Merql\Identity\IdentityRule;

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

Vrste pravil:

Vrsta Pomen
primary Stolpci primarnega ključa podatkovne zbirke
natural Stabilni enolični poslovni stolpci
composite Stolpci sestavljene logične identitete
content Rezervna možnost z zgoščeno vrednostjo vsebine

IdentityRule::forSchema($schema) določi privzeto pravilo:

  1. Če ima tabela primarni ključ, uporabi stolpce primarnega ključa.
  2. Če ima tabela enolične ključe, uporabi stolpce prvega enoličnega ključa.
  3. Če nima nobenega od njih, uporabi vse stolpce (rezervna možnost z zgoščeno vrednostjo vsebine).

IdentityRuleSet

Uporabite IdentityRuleSet, kadar gostiteljska aplikacija pozna boljše pravilo identitete kot privzeto pravilo sheme.

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 za vsako zajeto tabelo določi IdentityRule. Izbrani stolpci so shranjeni v TableSnapshot::identityColumns in uporabljeni pri vseh nadaljnjih operacijah diff, merge, plan, SQL in rollback.

Merql::init() lahko prejme isti nabor pravil tudi pri uporabi statičnega vmesnika:

PHP
use Merql\Merql;

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

Nabori pravil imajo stabilno serializacijo polj:

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

Neenolična identiteta

Če imata dve zajeti vrstici isti ključ identitete, zajem ne uspe, namesto da bi eno vrstico prepisal z drugo.

PHP
use Merql\Exceptions\SnapshotException;

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

Gostiteljske aplikacije lahko pred zajemom preverijo surove vrstice z IdentityRuleSet::conflictsFor(), če želijo neenoličnost zaznati še pred zajemom:

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

Za WordPress-jeve metatabele je post_id + meta_key običajno uporaben za združevanje v skupine in prikaz, ni pa varen za identifikacijo vrstic, ker so podvojeni ključi meta veljavni. Za identiteto vrstice uporabite primarni ključ tabele, razen če lahko gostiteljska aplikacija dokaže, da je naravni ključ enoličen.

Kodiranje ključa vrstice

Ključi vrstic so kodirani nizi, ki združujejo vrednosti več stolpcev z ločilom enote (\x1F). Vrednosti, ki vsebujejo ločilo ali znak za odstotek, so ubežno kodirane, da se preprečijo kolizije:

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']

Pravila ubežnega kodiranja:

Izvirnik Ubežano
% %25
\x1F (ločilo enot) %1F

To zagotavlja, da se vrednost, ki vsebuje \x1F, ne razdeli na več delov ključa. Kodiranje je deterministično in reverzibilno.

Razhajanje samodejnega povečevanja

Ko obe strani vstavita nove vrstice, se ID-ji samodejnega povečevanja med vejami razlikujejo. Vrstica #100 v naši kopiji je lahko povsem drug zapis kot vrstica #100 v njihovi kopiji.

merql to obravnava tako, da primerja primarne ključe. Če obe strani vstavita vrstico z istim ID-jem samodejnega povečevanja, je označena kot spor insert_insert. Da bi se temu izognili, za tabele, v katere se pričakujejo sočasni vnosi, uporabite naravne ključe (enolične stolpce, ki so stabilni med vejami).

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

Identiteta v posnetkih

Stolpci identitete, izbrani med zajemom, so shranjeni z vsakim TableSnapshot:

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

Ti stolpci se uporabljajo za SqlGenerator za tvorjenje stavkov WHERE za UPDATE in DELETE, načrti združevanja pa z njimi prikažejo dekodirane vrednosti identitete za pregled, izbiro, varovano uporabo in povrnitev.