数据库连接
数据库可以处理有限数量的并发连接。每个连接都需要 RAM,这意味着只需增加数据库连接限制而无需扩展可用资源:
连接池的工作原理
查询引擎用 可配置池大小 和 池超时 实例化一个连接池。
查询引擎创建一个连接并将其添加到连接池中。
当查询到来时,查询引擎会从池中保留一个连接来处理查询。
如果连接池中没有可用的空闲连接,则查询引擎会打开额外的数据库连接并将其添加到连接池中,直到数据库连接数达到 connection_limit 定义的限制。
如果查询引擎无法从池中保留连接,查询将添加到内存中的 FIFO(先进先出)队列中。FIFO 意味着查询按照进入队列的顺序进行处理。
如果查询引擎无法在 时限 之前处理队列中的查询,则会针对该查询引发错误代码为 P2024 的异常,并继续处理队列中的下一个查询。
连接池大小
默认
CPU的个数 * 2 +1
举个例子: 你的服务器有 4 个物理 CPU,则你的连接池将包含 9 个链接(4*2+1=9)
设置连接池大小
- 5 可以换成你需要的数量
datasource db {
provider = "mysql"
url = "mysql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5"
}
查看连接池大小
const prisma = new PrismaClient({
log: ["info"],
});
async function main() {
const users = await prisma.user.findMany(); // user 换成你的表名
console.log(users);
}
- 这样就会打印出来
prisma:info Starting a mysql pool with 17 connections.
连接池超时
- 默认超时
默认连接池超时时间为 10
秒。如果查询引擎在这段时间内没有从数据库连接池获取连接,它将引发异常并继续执行队列中的下一个查询
- 设置连接池超时时间
你可以通过在数据库连接 URL 中显式设置 pool_timeout 参数来指定池超时。在以下示例中,池在 20 秒后超时:
datasource db {
provider = "mysql"
url = "mysql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=20"
}
- 禁用连接池超时
你可以通过将 pool_timeout 参数设置为 0 来禁用连接池超时:
datasource db {
provider = "mysql"
url = "mysql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=0"
}
链接管理
- 链接方式
注意
$connect() 开启链接
$disconnect() // 关闭链接
大多数时候 你不需要显示调用,当你运行第一个查询的时候,PrismaClient
会自动链接,并创建连接池
$connect
- 显示调用
const prisma = new PrismaClient();
// run inside `async` function
await prisma.$connect();
$disconnect
- 流程
注意
当你调用$disconnect 的时候
运行 beforeExit 钩子函数
结束查询并关闭所有的连接
- 显示调用
你应该显示调用$disconnect
就是脚本:
注意
不经常运行(例如,每晚发送电子邮件的计划作业),这意味着它不会从与数据库的长时间运行连接中受益
存在于长时间运行的应用的上下文中,例如后台服务。如果应用永远不会关闭,Prisma 客户端永远不会断开连接。
举例如下:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const emailService = new EmailService();
async function main() {
const allUsers = await prisma.user.findMany();
const emails = allUsers.map((x) => x.email);
await emailService.send(emails, "Hello!");
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
退出钩子(一般不用)
- 仅仅能在二进制查询引擎使用
const prisma = new PrismaClient();
prisma.$on("beforeExit", async () => {
console.log("beforeExit hook");
// PrismaClient still available
await prisma.message.create({
data: {
message: "Shutting down server",
},
});
});
主从分离
- 主服务器负责写入 , 从服务器负责读取
mysql 具体的 bin 参考 mysql 章节
prisma 设置主从分离
- 安装扩展
npm install @prisma/extension-read-replicas
- 设置读取扩展
通过扩展 Prisma 客户端实例来初始化扩展,并为扩展提供一个指向扩展的 url 选项中的只读副本的连接字符串。
import { PrismaClient } from "../generated/prisma";
import { readReplicas } from "@prisma/extension-read-replicas";
const HuanJing = process.env.DATABASE_URL_REPLICA; // .env文件里面写你的从服务器地址
const prisma = new PrismaClient({
log: ["info"],
}).$extends(
readReplicas({
url: HuanJing || "",
})
);
async function main() {
const posts = await prisma.post.findMany(); // user 换成你的表名
console.log(posts);
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
- 如果是多个从服务器
import { PrismaClient } from "../generated/prisma";
import { readReplicas } from "@prisma/extension-read-replicas";
const HuanJing = [process.env.DATABASE_URL_REPLICA || "", ""];
const prisma = new PrismaClient({
log: ["info"],
}).$extends(
readReplicas({
url: HuanJing || [],
})
);
- 从主数据库进行读取操作
你可以使用 $primary()
方法对主数据库显式执行读取操作:
const posts = await prisma.$primary().post.findMany();
- 对数据库副本执行操作
你可以使用 $replica()
方法对副本而不是主数据库显式执行查询:
const result = await prisma.$replica().user.findFirst(...)
注意
这样 写入操作就会走
schema.prisma
里面的配置的 db 地址读取就会走
DATABASE_URL_REPLICA