From 8283d4ddb5bb2c4cd85c4e148d583fca75f963a2 Mon Sep 17 00:00:00 2001 From: Brian Brennglass Date: Tue, 20 Aug 2024 23:48:41 -0400 Subject: [PATCH] almost done --- .../database/prisma-error-managment.mdx | 204 +++++++++--------- apps/docs/content/guides/database/prisma.mdx | 4 +- 2 files changed, 103 insertions(+), 105 deletions(-) diff --git a/apps/docs/content/guides/database/prisma-error-managment.mdx b/apps/docs/content/guides/database/prisma-error-managment.mdx index c7bf26f2596..2c7fe54b27b 100644 --- a/apps/docs/content/guides/database/prisma-error-managment.mdx +++ b/apps/docs/content/guides/database/prisma-error-managment.mdx @@ -68,15 +68,16 @@ Prisma is unable to allocate connections to pending queries fast enough to meet - Reduce the connection limit: If you've explicitly increased the `connection_limit` parameter in your Prisma configuration, try reducing it to a more reasonable value. - Increase pool size: If you are connecting with Supavisor, try increasing the pool size in the [Database Settings](https://supabase.com/dashboard/project/_/settings/database). - Optimize queries: [Improve the efficiency of your queries](https://supabase.com/docs/guides/database/query-optimization) to reduce execution time. - - Increase compute size: Like the above option, this is a strategy to reduce query exeuction time. + - Increase compute size: Like the preceding option, this is a strategy to reduce query execution time. - Increase the pool timeout: Increase the `pool_timeout` parameter in your Prisma configuration to give the pooler more time to allocate connections. ### Server has closed the connection -According to this [GitHub Issue for Prisma](https://github.com/prisma/prisma/discussions/7389), this error may be related to large return values for queries. +According to this [GitHub Issue for Prisma](https://github.com/prisma/prisma/discussions/7389), this error may be related to large return values for queries. It may also be caused by significant database strain. - **Solution:** - Try to limit the total amount of rows returned for particularly large requests. + - Check the Reports Page for database strain. If there is obvious strain, consider [optomizing](https://supabase.com/docs/guides/database/query-optimization) or increasing compute size ## Drift detected: Your database schema is not in sync with your migration history @@ -90,6 +91,32 @@ Prisma relies on migration files to ensure your database aligns with Prisma's mo - **Solution** - Baselining migrations: [baselining](https://www.prisma.io/docs/orm/prisma-migrate/workflows/baselining) re-syncs Prisma by capturing the current database schema as the starting point for future migrations. +## Max client connections reached + +Postgres or Supavisor rejected a request for more connections + +- **Likely Causes:** +- When working in transaction mode (port 6543): The error "Max client connections reached" occurs when clients try to form more connections with the pooler than it can support. +- When working in session mode (port 5432), the max amount of clients is restricted to the "Pool Size" value in the [Database Settings](https://supabase.com/dashboard/project/_/settings/database). If the "Pool Size" is set to 15, even if the pooler can handle 200 client connections, it will still be effectively capped at 15 for each unique ["database-role+database" combination](https://github.com/orgs/supabase/discussions/21566). +- When working with direct connections: Postgres is already servicing the max amount of connections + +- **Solutions** + +- **Transaction Mode for Serverless Apps**: If you are using serverless functions (Supabase Edge, Vercel, AWS Lambda), switch to transaction mode (port 6543). It handles more connections than session mode or direct connections. +- **Reduce the number of connections**: A single client-server can establish multiple connections with a pooler. Typically, serverless setups do not need many connections. Starting with fewer, like five or three, or even just one, is often sufficient. In serverless setups, begin with `connection_limit=1`, increasing cautiously if needed to avoid maxing out connections. + +- **Decrease query time**: Reduce query complexity or add [strategic indexes](https://supabase.com/docs/guides/database/postgres/indexes) to your tables to speed up queries. + +- **Increase Compute Size**: Sometimes the best option is to increase your compute size, which also increases your max client size and query execution speed + +- **Disconnect Appropriately**: Close Prisma connections when they are no longer needed. + +- **Increase your pool size**: If the pooler lacks sufficient direct connections (due to a small pool size), it may struggle to allocate database connections to clients, leading to an overflow in the queue of waiting clients. This overflow could result in exceeding the client connection limits. + +Typically, when using the REST API, you can increase your "Pool Size" in the [Dashboard](https://supabase.com/dashboard/project/_/settings/database) to 40% of your total database connections, and up to 80% if you're not using the REST API. For example, if your instance supported 60 direct connections, you could cautiously raise the pool size to 24 if you were relying on the REST API or 48 if you were not. + +However, the recommended maximums provided are imperfect estimates and it may be possible that your usage patterns may allow for higher values. It's also possible that you'd end up using too many database connections, preventing critical servers from interacting with your database. It's best to tailor the number based on your current usage. + ## Cross schema references are only allowed when the target schema is listed in the schemas property of your datasource A Prisma migration is referencing a schema it is not permitted to manage. @@ -122,115 +149,86 @@ An alternative strategy to reference these tables is to duplicate values into Pr
Show/Hide Details -```sql -create table public.profiles ( -id uuid primary key, -full_name varchar(256), -email -) + + ```sql table_in_public + -- Create the 'profiles' table in the 'public' schema + create table public.profiles ( + id uuid primary key, -- 'id' is a UUID and the primary key for the table + full_name varchar(256), -- 'full_name' is a variable character field with a maximum length of 256 characters + email varchar(256) -- 'email' is a variable character field with a maximum length of 256 characters + ); + ``` - create function public.handle_new_user() - returns trigger as $$ - begin - insert into public.profiles (id, full_name, email) - values (new.id, new.raw_user_meta_data->>'full_name', new.email); - return new; - end; + ```sql trigger_on_insert + -- Function to handle the insertion of a new user into the 'profiles' table + create function public.handle_new_user() + returns trigger + language plpgsql + security definer set search_path = '' + as $$ + begin + -- Insert the new user's data into the 'profiles' table + insert into public.profiles (id, full_name, email) + values (new.id, new.raw_user_meta_data->>'full_name', new.email); - $$ - language plpgsql security definer; + return new; -- Return the new record + end; + $$; + ``` - create function public.update_user() - returns trigger as - $$ + ```sql trigger_on_update + -- Function to handle the updating of a user's information in the 'profiles' table + create function public.update_user() + returns trigger + language plpgsql + security definer set search_path = '' + as + $$ + begin + -- Update the user's data in the 'profiles' table + update public.profiles + set full_name = new.raw_user_meta_data->>'full_name', -- Update the 'full_name' field + email = new.email -- Update the 'email' field + where id = new.id; -- Match the 'id' field with the new record - begin - update public.profiles (full_name, avatar_url) - set full_name = new.raw_user_meta_data->>'full_name', email = new.email - where id = new.id - return new; - end; + return new; -- Return the new record + end; + $$; + ``` - $$ - language plpgsql security definer; + ```sql trigger_on_delete + -- Function to handle the deletion of a user from the 'profiles' table + create function public.delete_user() + returns trigger + language plpgsql + security definer set search_path = '' + as + $$ + begin + -- Delete the user's data from the 'profiles' table + delete from public.profiles + where id = old.id; -- Match the 'id' field with the old record - create function public.delete_user() - returns trigger as - $$ + return old; -- Return the old record + end; + $$; + ``` - begin - delete from public.profiles - where id = old.id - return old; - end; + ```sql triggers_on_auth + -- Trigger to run 'handle_new_user' function after a new user is inserted into 'auth.users' table + create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); - $$ - language plpgsql security definer; + -- Trigger to run 'update_user' function after a user is updated in the 'auth.users' table + create trigger on_auth_user_updated + after update on auth.users + for each row execute procedure public.update_user(); - create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); + -- Trigger to run 'delete_user' function after a user is deleted from the 'auth.users' table + create trigger on_auth_user_deleted + after delete on auth.users + for each row execute procedure public.delete_user(); + ``` - create trigger on_auth_user_updated - after update on auth.users - for each row execute procedure public.update_user(); - - create trigger on_auth_user_deleted - after delete on auth.users - for each row execute procedure public.delete_user(); - -````
-## `Max client connections reached` - -Postgres or Supavisor rejected a request for more connections - -- **Likely Causes:** -- When working in transaction mode (port 6543): The error "Max client connections reached" occurs when clients try to form more connections with the pooler than it can support. For example, if you were using a compute size that supported 200 max clients, and tried to form 201 connections with the pooler, the 201th connection would receive the error message. -- When working in session mode (port 5432), the max amount of clients is restricted to the "Pool Size" value in the [Database Settings](https://supabase.com/dashboard/project/_/settings/database). If the "Pool Size" is set to 15, even if the pooler can handle 200 client connections, it will still be effectively capped at 15 for each unique ["database-role+database" combination](https://github.com/orgs/supabase/discussions/21566). If there are 16 connection attempts, only the first 15 will be accepted. The 16th connection will queue in the pooler for up to a minute. It will encounter a "Max client connections reached" error and be rejected If no other clients disconnect voluntarily during this time. -- When working with direct connections: Postgres is already servicing the max amount of connections - -- **Solutions** - -1. If you are using session mode, consider using transaction mode, instead: - -Transaction mode typically enables higher query throughput and supports more clients than session mode. It's especially suitable for serverless applications like those deployed on Supabase Edge Functions, Vercel Functions, or AWS Lambda. For a more in-depth explanation, check out the [Supavisor FAQ](https://github.com/orgs/supabase/discussions/21566) - -Transaction mode does not support prepared statements. They're pre-parsed queries that some libraries may create for moderate performance benefits. You should look at how to disable prepared statements ([guide](https://github.com/orgs/supabase/discussions/28239)) for your connection library to prevent the following error from occurring: - -> ... prepared statement "statement_name" already exists" - -2. Reduce the number of connections created by your application servers - -A single client-server can establish multiple connections with a pooler. For instance, using the Prisma library, you could hypothetically set the connection_limit configuration to spawn 1000 client connections. Here's an example: - -```js -datasource db { - provider = "postgresql" - url = "postgres://[db-user].[project-ref]:[db-password]@aws-0-[aws-region].pooler.supabase.com:6543/[db-name]?pgbouncer=true&connection_limit=1000 -} -```` - -Typically, serverless setups do not need many connections. Starting with fewer, like five or three, or even just one, is often sufficient. In serverless setups, begin with `connection_limit=1`, increasing cautiously if needed to avoid maxing out connections. - -3. Increase your pool size - -If the pooler lacks sufficient direct connections (due to a small pool size), it may struggle to allocate database connections to clients, leading to an overflow in the queue of waiting clients. This overflow could result in exceeding the client connection limits. - -Typically, when using the REST API, you can increase your "Pool Size" in the [Dashboard](https://supabase.com/dashboard/project/_/settings/database) to 40% of your total database connections, and up to 80% if you're not using the REST API. For example, if your instance supported 60 direct connections, you could cautiously raise the pool size to 24 if you were relying on the REST API or 48 if you were not. - -However, the recommended maximums provided are imperfect estimates and it may be possible that your usage patterns may allow for higher values. It's also possible that you'd end up using too many database connections, preventing critical servers from interacting with your database. - -It's best to tailor the number based on your current usage. - -4. Decrease Query Time - -Reduce query complexity or add [strategic indexes](https://supabase.com/docs/guides/database/postgres/indexes) to your tables to speed up queries. - -5. Increase Compute Size - -Sometimes the best option is to increase your compute size, which also increases your max client size and query execution speed - -6. Disconnect Appropriately - -Close Prisma connections when they are no longer needed. diff --git a/apps/docs/content/guides/database/prisma.mdx b/apps/docs/content/guides/database/prisma.mdx index a90c55a2c51..691a9d7e145 100644 --- a/apps/docs/content/guides/database/prisma.mdx +++ b/apps/docs/content/guides/database/prisma.mdx @@ -119,10 +119,10 @@ If you plan to solely use Prisma instead of the Supabase Postgres API, turn it o - Add a DATABASE_URL variable to your .env file. This is for your Supavisor Transaction mode string, which is necessary for managing serverless environments. It uses port 6543 and requires two flags appended to the the end of the string: "pgbouncer=true&connection_limit=1" + Add a DATABASE_URL variable to your .env file. This is for your Supavisor Transaction mode string, which is necessary for managing serverless environments. It uses port 6543 and requires a flag appended to the the end of the string: "pgbouncer=true" ```text .env # Used in your application - DATABASE_URL="postgres://prisma.qjqzlvutjxbyodxrrvhb:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1" + DATABASE_URL="postgres://prisma.qjqzlvutjxbyodxrrvhb:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:6543/postgres?pgbouncer=true" # Used for Prisma Migrations DIRECT_URL="postgres://prisma.qjqzlvutjxbyodxrrvhb:[YOUR-PASSWORD]@aws-0-us-east-1.pooler.supabase.com:5432/postgres"