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

Κατοπτρισμός SQL

Το SqlMirror προωθεί συλλογές storh σε πίνακες SQLite ή MySQL, ώστε να μπορείτε να εκτελείτε συνδέσεις, ταξινόμηση μεταξύ πινάκων, αναζήτηση υποσυμβολοσειρών και δημιουργία αναφορών στο SQL, ενώ τα αρχεία παραμένουν κανονικά. Σκεφτείτε το ως δευτερεύον ευρετήριο που τυχαίνει να είναι βάση δεδομένων: το κατοπτρικό αντίγραφο παράγεται από τα αρχικά δεδομένα, είναι αναλώσιμο και μπορεί να αναδημιουργηθεί ανά πάσα στιγμή. Απαιτείται το ext-pdo με τον οδηγό sqlite ή mysql μόνο όταν το χρησιμοποιείτε· το βασικό πακέτο δεν έχει εξαρτήσεις.

Ρύθμιση

PHP
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();

Και οι δύο μηχανές μπορούν να κατοπτριστούν: συλλογές DocStore και ροές SegmentedLog (προωθούνται μόνο οι ενεργές εγγραφές). Η παροχή ενός Schema είναι προαιρετική και ανεξάρτητη από τον αποθηκευτικό χώρο: τα δηλωμένα πεδία string/int/float/bool γίνονται τυποποιημένες στήλες με ευρετήριο· όλα τα υπόλοιπα παραμένουν αναζητήσιμα στη στήλη data JSON. Τα πεδία mixed δεν μπορούν να επισημανθούν για ευρετηρίαση.

Συνδέσεις

Ο κατασκευαστής δέχεται μια λαβή PDO (οδηγός sqlite ή mysql, εντοπίζεται αυτόματα), μια λαβή mysqli ή οποιαδήποτε υλοποίηση SqlMirrorConnection:

PHP
$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_');

Η διαδρομή mysqli λειτουργεί και με τους δύο τρόπους αναφοράς σφαλμάτων του mysqli, επομένως μια υπάρχουσα λαβή από εφαρμογή φιλοξενίας (για παράδειγμα το $wpdb->dbh του WordPress) μπορεί να επαναχρησιμοποιηθεί ως έχει. Η συμπεριφορά είναι ίδια σε όλους τους οδηγούς· οι αποτυχίες προώθησης επαναφέρουν τη συναλλαγή της συλλογής σε όλους.

Κάθε πίνακας αποκτά τα id (πρωτεύον κλειδί), hash (καθορίζει τις σταδιακές προωθήσεις), τις τυποποιημένες στήλες και το data (την πλήρη εγγραφή JSON).

Συγχρονισμός

PHP
$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() συγκρίνει τα αποτυπώματα κατακερματισμού των εγγραφών με το κατοπτρικό αντίγραφο και γράφει κάθε συλλογή σε μία συναλλαγή, ώστε μια διακοπή λειτουργίας ή αποτυχία κατά την προώθηση να μην αφήνει ποτέ μια παρτίδα μισοεφαρμοσμένη. Για τις αμετάβλητες εγγραφές απαιτείται ένα SELECT και σάρωση εγγραφών. Μια περιοδική εκτέλεση του push() (για παράδειγμα από ένα χρονόμετρο cron) διατηρεί το κατοπτρικό αντίγραφο συγχρονισμένο· καλέστε το flush() με τα αναγνωριστικά που γράψατε κατά τη διάρκεια ενός αιτήματος, όταν οι αναγνώστες πρέπει να βλέπουν στο κατοπτρικό αντίγραφο τις εγγραφές που μόλις γράφτηκαν.

Ερωτήματα

Υποβάλετε ερωτήματα στο κατοπτρικό αντίγραφο με απλό SQL. Το table() επιστρέφει το όνομα του κατοπτρισμένου πίνακα:

PHP
$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'
);

Επαναφορά στα αρχεία

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

  • Επαναφορά: τα αρχεία έχουν χαθεί, αλλά το κατοπτρικό αντίγραφο διατηρείται. Καταχωρίστε έναν νέο αποθηκευτικό χώρο με το ίδιο όνομα συλλογής και πραγματοποιήστε ανάκτηση.
  • Αρχική φόρτωση: γραμμές που έχουν φορτωθεί στον πίνακα του κατοπτρικού αντιγράφου μέσω εξωτερικών εργαλείων γίνονται εγγραφές storh. Οι γραμμές πρέπει να περιέχουν έγκυρα αναγνωριστικά UUIDv7 και ένα αντικείμενο στη στήλη data· κατά την ανάκτηση αγνοούνται οι τυποποιημένες στήλες, επειδή το data είναι ολόκληρη η εγγραφή.
PHP
$restored = new Storh\DocStore($root, 'pages');
$mirror   = new SqlMirror($pdo);
$mirror->collection($restored, 'pages');
$mirror->pull();          // ['written' => n, 'unchanged' => m]

Οι εγγραφές που ανακτώνται περνούν από τον κανονικό μηχανισμό αποθήκευσης, επομένως εφαρμόζονται η επικύρωση σχήματος και τα μοναδικά ευρετήρια, ενώ κάθε εγγραφή γράφεται με ανθεκτικό τρόπο. Το pull() δεν διαγράφει ποτέ τοπικές εγγραφές και παραλείπει όσες έχουν ήδη τα ίδια δεδομένα με τη γραμμή του κατοπτρικού αντιγράφου. Μετά την αρχική φόρτωση γραμμών που εισήχθησαν χειροκίνητα, εκτελέστε μία φορά το push(): ξαναγράφει αυτές τις γραμμές στην κανονική μορφή τους, ώστε να συμφωνούν τα αποτυπώματά τους.

Συμβόλαιο και περιορισμοί

  • Τα αρχεία είναι η κανονική πηγή. Το κατοπτρικό αντίγραφο είναι έξοδος μόνο για ανάγνωση· οτιδήποτε γράφεται σε αυτό χειροκίνητα αντικαθίσταται ή διαγράφεται στην επόμενη εκτέλεση του push().
  • Οι μοναδικές στήλες στο κατοπτρικό αντίγραφο λειτουργούν ως δικλείδα ασφαλείας, όχι ως επιβολή κατά τη στιγμή της εγγραφής: ένα διπλότυπο που επέτρεψαν τα αρχεία εμφανίζεται ως αποτυχημένη προώθηση που επαναφέρεται πλήρως. Για επιβολή κατά την εγγραφή, χρησιμοποιήστε μοναδικά ευρετήρια storh.
  • Το κατοπτρικό αντίγραφο υστερεί έως ένα διάστημα προώθησης σε σχέση με τα αρχεία, εκτός από τα αναγνωριστικά που flush() ρητά.
  • Ο κατοπτρισμός δεν προσθέτει συναλλαγές στο ίδιο το storh. Οι ατομικές εγγραφές πολλών εγγραφών παραμένουν υπόθεση πραγματικής βάσης δεδομένων, ως συστήματος καταγραφής.
  • Οι αλλαγές σχήματος εφαρμόζονται με απόρριψη και επανεγκατάσταση του κατοπτρικού αντιγράφου: uninstall(), install(), push().