Configuración de múltiples fuentes de datos, bases de datos, esquemas y replicación
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Uso de múltiples fuentes de datos
Para usar múltiples fuentes de datos conectadas a diferentes bases de datos, simplemente crea varias instancias de DataSource:
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,
})
Uso de múltiples bases de datos en una sola fuente de datos
Para utilizar múltiples bases de datos en una sola fuente de datos, puedes especificar el nombre de la base de datos por entidad:
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
}
La entidad User se creará dentro de la base de datos secondDB y la entidad Photo dentro de thirdDB.
Todas las demás entidades se crearán en la base de datos predeterminada definida en las opciones de la fuente de datos.
Si deseas seleccionar datos de una base de datos diferente, solo necesitas proporcionar una entidad:
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
Este código producirá la siguiente consulta SQL (dependiendo del tipo de base de datos):
SELECT * FROM "secondDB"."user" "user", "thirdDB"."photo" "photo"
WHERE "photo"."userId" = "user"."id"
También puedes especificar una ruta de tabla en lugar de la entidad:
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
Esta característica solo es compatible con bases de datos MySQL y MSSQL.
Uso de múltiples esquemas en una sola fuente de datos
Para usar múltiples esquemas en tus aplicaciones, simplemente establece schema en cada entidad:
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
}
La entidad User se creará dentro del esquema secondSchema y la entidad Photo dentro de thirdSchema.
Todas las demás entidades se crearán en la base de datos predeterminada definida en las opciones de la fuente de datos.
Si deseas seleccionar datos de un esquema diferente, solo necesitas proporcionar una entidad:
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
Este código producirá la siguiente consulta SQL (dependiendo del tipo de base de datos):
SELECT * FROM "secondSchema"."question" "question", "thirdSchema"."photo" "photo"
WHERE "photo"."userId" = "user"."id"
También puedes especificar una ruta de tabla en lugar de la entidad:
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()
Esta característica solo es compatible con bases de datos PostgreSQL y MSSQL. En MSSQL también puedes combinar esquemas y bases de datos, por ejemplo:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity({ database: "secondDB", schema: "public" })
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
}
Replicación
Puedes configurar replicación de lectura/escritura usando TypeORM. Ejemplo de opciones de replicación:
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",
},
],
},
})
Con esclavos de replicación definidos, TypeORM enviará todas las consultas posibles a los esclavos por defecto.
-
todas las consultas realizadas por los métodos
findoSelectQueryBuilderusarán una instanciaslavealeatoria -
todas las consultas de escritura realizadas por
update,create,InsertQueryBuilder,UpdateQueryBuilder, etc. usarán la instanciamaster -
todas las consultas directas (raw queries) realizadas llamando a
.query()usarán la instanciamaster -
todas las operaciones de actualización del esquema se realizarán usando la instancia
master
Selección explícita de destinos de consulta
Por defecto, TypeORM enviará todas las consultas de lectura a un esclavo de lectura aleatorio y todas las escrituras al maestro. Esto significa que cuando agregas por primera vez la configuración de replication, cualquier ejecutor de consultas de lectura existente que no especifique explícitamente un modo de replicación comenzará a dirigirse a un esclavo. Esto es bueno para la escalabilidad, pero si algunas de esas consultas deben devolver datos actualizados, entonces necesitas pasar explícitamente un modo de replicación al crear un ejecutor de consultas.
Si deseas usar explícitamente el master para consultas de lectura, pasa un ReplicationMode explícito al crear tu QueryRunner:
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()
}
Si deseas usar un esclavo en consultas directas (raw queries), pasa slave como modo de replicación al crear un ejecutor de consultas:
const slaveQueryRunner = dataSource.createQueryRunner("slave")
try {
const userFromSlave = await slaveQueryRunner.query(
"SELECT * FROM users WHERE id = $1",
[userId],
slaveQueryRunner,
)
} finally {
return slaveQueryRunner.release()
}
Nota: Las instancias de QueryRunner creadas manualmente deben liberarse explícitamente por sí mismas. Si no liberas tus ejecutores de consultas, mantendrán una conexión reservada del grupo e impedirán que otras consultas la utilicen.
Ajuste del destino predeterminado para lecturas
Si no quieres que todas las lecturas vayan a una instancia slave por defecto, puedes cambiar el destino predeterminado de consultas de lectura pasando defaultMode: "master" en tus opciones de replicación:
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",
},
],
},
})
Con este modo, ninguna consulta irá a los esclavos de lectura por defecto, y deberás optar explícitamente por enviar consultas a esclavos de lectura con llamadas .createQueryRunner("slave").
Si estás agregando opciones de replicación a una aplicación existente por primera vez, esta es una buena opción para garantizar que no haya cambios de comportamiento inmediatos, y en su lugar puedes adoptar lentamente réplicas de lectura en base a cada query runner.
Controladores admitidos
La replicación es compatible con los controladores de conexión MySQL, PostgreSQL, SQL Server, Cockroach, Oracle y Spanner.
La replicación de MySQL admite opciones de configuración adicionales:
{
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"
}
}