Mehrere Datenquellen, Datenbanken, Schemas und Replikationssetup
Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →
Verwendung mehrerer Datenquellen
Um mehrere Datenquellen zu verwenden, die mit verschiedenen Datenbanken verbunden sind, erstellen Sie einfach mehrere DataSource-Instanzen:
import { DataSource } from "typeorm"
const db1DataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "admin",
database: "db1",
entities: [__dirname + "/entities/*{.js,.ts}"],
synchronize: true,
})
const db2DataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "admin",
database: "db2",
entities: [__dirname + "/entities/*{.js,.ts}"],
synchronize: true,
})
Verwendung mehrerer Datenbanken innerhalb einer einzelnen Datenquelle
Um mehrere Datenbanken in einer einzelnen Datenquelle zu verwenden, können Sie den Datenbanknamen pro Entität angeben:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity({ database: "secondDB" })
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
}
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity({ database: "thirdDB" })
export class Photo {
@PrimaryGeneratedColumn()
id: number
@Column()
url: string
}
Die User-Entität wird in der Datenbank secondDB und die Photo-Entität in der Datenbank thirdDB erstellt.
Alle anderen Entitäten werden in der Standarddatenbank erstellt, die in den Datenquellenoptionen definiert ist.
Wenn Sie Daten aus einer anderen Datenbank auswählen möchten, müssen Sie nur eine Entität angeben:
const users = await dataSource
.createQueryBuilder()
.select()
.from(User, "user")
.addFrom(Photo, "photo")
.andWhere("photo.userId = user.id")
.getMany() // userId is not a foreign key since its cross-database request
Dieser Code erzeugt die folgende SQL-Abfrage (abhängig vom Datenbanktyp):
SELECT * FROM "secondDB"."user" "user", "thirdDB"."photo" "photo"
WHERE "photo"."userId" = "user"."id"
Sie können auch einen Tabellenpfad anstelle der Entität angeben:
const users = await dataSource
.createQueryBuilder()
.select()
.from("secondDB.user", "user")
.addFrom("thirdDB.photo", "photo")
.andWhere("photo.userId = user.id")
.getMany() // userId is not a foreign key since its cross-database request
Diese Funktion wird nur in MySQL- und MSSQL-Datenbanken unterstützt.
Verwendung mehrerer Schemas innerhalb einer einzelnen Datenquelle
Um mehrere Schemas in Ihren Anwendungen zu verwenden, setzen Sie einfach schema für jede Entität:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity({ schema: "secondSchema" })
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
}
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity({ schema: "thirdSchema" })
export class Photo {
@PrimaryGeneratedColumn()
id: number
@Column()
url: string
}
Die User-Entität wird im Schema secondSchema und die Photo-Entität im Schema thirdSchema erstellt.
Alle anderen Entitäten werden in der Standarddatenbank erstellt, die in den Datenquellenoptionen definiert ist.
Wenn Sie Daten aus einem anderen Schema auswählen möchten, müssen Sie nur eine Entität angeben:
const users = await dataSource
.createQueryBuilder()
.select()
.from(User, "user")
.addFrom(Photo, "photo")
.andWhere("photo.userId = user.id")
.getMany() // userId is not a foreign key since its cross-database request
Dieser Code erzeugt die folgende SQL-Abfrage (abhängig vom Datenbanktyp):
SELECT * FROM "secondSchema"."question" "question", "thirdSchema"."photo" "photo"
WHERE "photo"."userId" = "user"."id"
Sie können auch einen Tabellenpfad anstelle der Entität angeben:
const users = await dataSource
.createQueryBuilder()
.select()
.from("secondSchema.user", "user") // in mssql you can even specify a database: secondDB.secondSchema.user
.addFrom("thirdSchema.photo", "photo") // in mssql you can even specify a database: thirdDB.thirdSchema.photo
.andWhere("photo.userId = user.id")
.getMany()
Diese Funktion wird nur in PostgreSQL- und MSSQL-Datenbanken unterstützt. In MSSQL können Sie auch Schemas und Datenbanken kombinieren, zum Beispiel:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity({ database: "secondDB", schema: "public" })
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
}
Replikation
Sie können Lese-/Schreibreplikation mit TypeORM einrichten. Beispiel für Replikationsoptionen:
const datasource = new DataSource({
type: "mysql",
logging: true,
replication: {
master: {
host: "server1",
port: 3306,
username: "test",
password: "test",
database: "test",
},
slaves: [
{
host: "server2",
port: 3306,
username: "test",
password: "test",
database: "test",
},
{
host: "server3",
port: 3306,
username: "test",
password: "test",
database: "test",
},
],
},
})
Wenn Replikationsslaves definiert sind, sendet TypeORM standardmäßig alle möglichen Abfragen an die Slaves.
-
Alle Abfragen, die durch die
find-Methoden oder denSelectQueryBuilderausgeführt werden, verwenden eine zufälligeslave-Instanz -
Alle Schreibabfragen durch
update,create,InsertQueryBuilder,UpdateQueryBuilderetc. verwenden diemaster-Instanz -
Alle Rohabfragen durch Aufruf von
.query()verwenden diemaster-Instanz -
Alle Schema-Aktualisierungsoperationen werden über die
master-Instanz durchgeführt
Explizite Auswahl von Abfragezielen
Standardmäßig sendet TypeORM alle Leseabfragen an einen zufälligen Leseslave und alle Schreibvorgänge an den Master. Wenn Sie erstmals replication-Einstellungen hinzufügen, werden bestehende Lese-QueryRunner ohne expliziten Replikationsmodus an Slaves gesendet. Dies fördert die Skalierbarkeit, aber wenn Abfragen zwingend aktuelle Daten benötigen, müssen Sie beim Erstellen eines QueryRunners explizit einen Replikationsmodus übergeben.
Um den master explizit für Leseabfragen zu verwenden, übergeben Sie beim Erstellen Ihres QueryRunner einen expliziten ReplicationMode:
const masterQueryRunner = dataSource.createQueryRunner("master")
try {
const postsFromMaster = await dataSource
.createQueryBuilder(Post, "post", masterQueryRunner) // you can either pass QueryRunner as an optional argument with query builder
.setQueryRunner(masterQueryRunner) // or use setQueryRunner which sets or overrides query builder's QueryRunner
.getMany()
} finally {
await masterQueryRunner.release()
}
Um einen Slave für Rohabfragen zu verwenden, übergeben Sie slave als Replikationsmodus beim Erstellen eines QueryRunners:
const slaveQueryRunner = dataSource.createQueryRunner("slave")
try {
const userFromSlave = await slaveQueryRunner.query(
"SELECT * FROM users WHERE id = $1",
[userId],
slaveQueryRunner,
)
} finally {
return slaveQueryRunner.release()
}
Hinweis: Manuell erstellte QueryRunner-Instanzen müssen explizit freigegeben werden. Andernfalls blockieren sie Verbindungen aus dem Pool und verhindern deren Weiterverwendung.
Anpassung des Standardziels für Lesevorgänge
Wenn nicht alle Lesevorgänge standardmäßig an slave-Instanzen gehen sollen, können Sie das Standardziel mit defaultMode: "master" in den Replikationsoptionen ändern:
const datasource = new DataSource({
type: "mysql",
logging: true,
replication: {
// set the default destination for read queries as the master instance
defaultMode: "master",
master: {
host: "server1",
port: 3306,
username: "test",
password: "test",
database: "test",
},
slaves: [
{
host: "server2",
port: 3306,
username: "test",
password: "test",
database: "test",
},
],
},
})
In diesem Modus gehen standardmäßig keine Abfragen an Leseslaves. Sie müssen explizit mit .createQueryRunner("slave")-Aufrufen opt-in.
Wenn Sie Replikationsoptionen erstmals zu einer bestehenden App hinzufügen, ist dies eine gute Option, um sicherzustellen, dass sich das Verhalten zunächst nicht ändert. Stattdessen können Sie Lesereplikas schrittweise auf Basis einzelner Query Runner übernehmen.
Unterstützte Treiber
Replikation wird von den MySQL-, PostgreSQL-, SQL Server-, Cockroach-, Oracle- und Spanner-Verbindungstreibern unterstützt.
Die MySQL-Replikation unterstützt zusätzliche Konfigurationsoptionen:
{
replication: {
master: {
host: "server1",
port: 3306,
username: "test",
password: "test",
database: "test"
},
slaves: [{
host: "server2",
port: 3306,
username: "test",
password: "test",
database: "test"
}, {
host: "server3",
port: 3306,
username: "test",
password: "test",
database: "test"
}],
/**
* If true, PoolCluster will attempt to reconnect when connection fails. (Default: true)
*/
canRetry: true,
/**
* If connection fails, node's errorCount increases.
* When errorCount is greater than removeNodeErrorCount, remove a node in the PoolCluster. (Default: 5)
*/
removeNodeErrorCount: 5,
/**
* If connection fails, specifies the number of milliseconds before another connection attempt will be made.
* If set to 0, then node will be removed instead and never re-used. (Default: 0)
*/
restoreNodeTimeout: 0,
/**
* Determines how slaves are selected:
* RR: Select one alternately (Round-Robin).
* RANDOM: Select the node by random function.
* ORDER: Select the first node available unconditionally.
*/
selector: "RR"
}
}