SQL-spegel
SqlMirror skickar storh-samlingar till tabeller i SQLite eller MySQL så att du kan
köra kopplingar, sortering över flera tabeller, delsträngssökning och rapportering i SQL medan
filerna förblir kanoniska. Se det som ett sekundärt index som råkar vara
en databas: spegeln härleds, kan kastas bort och kan byggas om när som helst.
ext-pdo med sqlite- eller mysql-drivrutinen krävs bara när du använder
funktionen; kärnpaketet är fortfarande fritt från beroenden.
Konfiguration
use Storh\DocStore;
use Storh\Schema;
use Storh\SqlMirror;
$schema = Schema::collection('pages')
->string('slug')->unique()
->string('kind')->index()
->int('publishedAt')->range();
$pages = new DocStore($root, 'pages', schema: $schema);
$events = new Storh\SegmentedLog($root, 'events');
$mirror = new SqlMirror(new PDO('sqlite:' . $root . '/mirror.db'), 'app_');
$mirror->collection($pages, 'pages', $schema);
$mirror->collection($events, 'events');
$mirror->install();
$mirror->push();
Båda motorerna kan speglas: DocStore-samlingar och SegmentedLog-strömmar (endast aktiva poster skickas). Det är valfritt att skicka en Schema och oberoende av lagret: deklarerade fält av typen string/int/float/bool blir typade, indexerade kolumner; allt annat förblir sökbart i kolumnen dataJSON. Fält av typen mixed kan inte flaggas för indexering.
Anslutningar
Konstruktorn accepterar ett PDO-handtag (drivrutinen sqlite eller mysql identifieras automatiskt), ett mysqli-handtag eller valfri implementation av SqlMirrorConnection:
$mirror = new SqlMirror(new PDO('sqlite:' . $root . '/mirror.db'));
$mirror = new SqlMirror(new PDO('mysql:host=127.0.0.1;dbname=app;charset=utf8mb4', $user, $password));
$mirror = new SqlMirror(new mysqli('127.0.0.1', $user, $password, 'app'), 'wp_storh_');
Sökvägen för mysqli fungerar med båda lägena för felrapportering i mysqli, så ett befintligt handtag från ett värdprogram (till exempel WordPresss $wpdb->dbh) kan återanvändas som det är. Beteendet är identiskt mellan drivrutinerna; misslyckade skickningar återställer samlingens transaktion i alla drivrutiner.
Varje tabell får id (primärnyckel), hash (driver inkrementella skickningar), de typade kolumnerna och data (hela postens JSON).
Synkronisering
$mirror->push(); // reconcile: insert, update, delete as needed
$mirror->push('pages'); // reconcile a single collection
$mirror->flush('pages', $ids); // push or remove just these ids
$mirror->pull(); // write mirror rows back into the store
$mirror->verify(); // report missing, stale, and orphaned rows
$mirror->rebuild(); // clear all rows and push from scratch
$mirror->uninstall(); // drop the mirror tables
push() jämför hashvärden för posterna med spegeln och skriver varje samling i
en transaktion, så en kraschad eller misslyckad skickning lämnar aldrig en delvis tillämpad
batch. Oförändrade poster kostar en SELECT plus en genomgång av posterna. En återkommande
push() (till exempel från ett cron-tick) håller spegeln uppdaterad; anropa
flush() med id:na du skrev under en begäran när läsare behöver
kunna läsa sina egna skrivningar från spegeln.
Frågor
Fråga spegeln med vanlig SQL. table() returnerar namnet på den speglade tabellen:
$pdo->query(
'SELECT p.slug, COUNT(*) AS sales
FROM ' . $mirror->table('purchases') . ' o
INNER JOIN ' . $mirror->table('products') . ' p ON p.id = o.product_id
GROUP BY p.slug
ORDER BY sales DESC'
);
Hämta tillbaka till filer
pull() läser spegelrader och skriver dem till det registrerade lagret i id-ordning. Den stöder två arbetsflöden:
- Återställning: filerna är borta, men spegeln finns kvar. Registrera ett nytt lager under samma samlingsnamn och hämta posterna.
- Förifyllning: rader som externa verktyg har läst in i spegeltabellen blir storh-poster. Raderna måste innehålla giltiga id:n av typen UUIDv7 och ett objekt i kolumnen
data; typade kolumner ignoreras vid hämtning eftersomdataär hela posten.
$restored = new Storh\DocStore($root, 'pages');
$mirror = new SqlMirror($pdo);
$mirror->collection($restored, 'pages');
$mirror->pull(); // ['written' => n, 'unchanged' => m]
Hämtade skrivningar går genom lagrets vanliga mekanismer, så schemavalidering och unika index tillämpas och varje post skrivs beständigt. pull() tar aldrig bort lokala poster, och poster vars data redan matchar spegelraden hoppas över. När du har förifyllt med manuellt infogade rader kör du push() en gång: det skriver om raderna i kanonisk form så att deras hashvärden stämmer överens.
Avtal och gränser
- Filerna är kanoniska. Spegeln är skrivskyddade utdata; allt som skrivs dit manuellt skrivs över eller tas bort vid nästa
push(). - Unika kolumner i spegeln fungerar som skyddsnät, inte som kontroll vid skrivning: en dubblett som filerna tillät leder till en misslyckad skickning som återställs helt. Använd storh unika index för kontroll vid skrivning.
- Spegeln kan ligga upp till ett skickningsintervall efter filerna, förutom för id:n som du uttryckligen
flush(). - Spegling lägger inte till transaktioner i själva storh. Atomära skrivningar över flera poster kräver fortfarande en riktig databas som källsystem.
- Schemaändringar tillämpas genom att spegeln tas bort och installeras om:
uninstall(),install(),push().