Skip to content

Commit fe5926a

Browse files
add sql review rule explain not valid (#939)
1 parent 267c39f commit fe5926a

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
title: 'SQL Review Rule Explained - Enforce NOT VALID in CHECK'
3+
author: Adela
4+
updated_at: 2025/11/13 22:00
5+
feature_image: /content/blog/sql-review-rule-explained-enforce-not-valid-in-check/banner.webp
6+
tags: Explanation
7+
description: Learn why enforcing NOT VALID in CHECK constraints is important and how the "Enforce NOT VALID in CHECK" review rule protects your production database.
8+
---
9+
10+
PostgreSQL allows you to add `CHECK` constraints to enforce data quality rules on a table. This is useful, but adding a CHECK constraint in the wrong way can block reads and writes and cause unexpected downtime.
11+
This SQL Review rule ensures that all new CHECK constraints are created using the safe, non-blocking approach.
12+
13+
## How CHECK Constraints Work
14+
15+
A CHECK constraint ensures that a column’s value satisfies a given condition, for example:
16+
17+
```sql
18+
CHECK (amount > 0)
19+
```
20+
21+
PostgreSQL will reject any insert or update that violates this rule.
22+
23+
To add a CHECK constraint, you typically run:
24+
25+
```sql
26+
ALTER TABLE orders
27+
ADD CONSTRAINT orders_positive CHECK (amount > 0);
28+
```
29+
30+
This enforces the rule on future writes, but it also immediately validates all existing rows.
31+
This is where the risk comes from.
32+
33+
## Why Adding CHECK Constraints Can Cause Downtime
34+
35+
When PostgreSQL validates an existing table, it must scan every row to confirm the constraint is not violated. During this step, it acquires an `ACCESS EXCLUSIVE` lock. This lock is the strongest one in PostgreSQL and can block:
36+
37+
* Reads
38+
* Writes
39+
* Other schema changes
40+
41+
On large tables or busy production databases, the lock can cause:
42+
43+
* Query timeouts
44+
* Application errors
45+
* Service degradation
46+
* Full outages
47+
48+
This SQL Review rule prevents teams from accidentally introducing blocking schema changes during deployments.
49+
50+
## The Safe Approach: Use `NOT VALID`
51+
52+
PostgreSQL offers a safer method to add CHECK constraints to existing tables.
53+
The idea is to separate constraint creation from constraint validation.
54+
55+
**Step 1: Create the constraint without validating existing rows**
56+
57+
```sql
58+
ALTER TABLE orders
59+
ADD CONSTRAINT orders_positive CHECK (amount > 0) NOT VALID;
60+
```
61+
62+
* Only a brief catalog lock is required
63+
* The constraint is enforced for all new inserts and updates
64+
* Existing rows are not scanned yet
65+
66+
**Step 2: Validate at a convenient time**
67+
68+
```sql
69+
ALTER TABLE orders
70+
VALIDATE CONSTRAINT orders_positive;
71+
```
72+
73+
Validation uses a lighter lock that does not block reads and writes.
74+
You can perform this step during low-traffic periods or as part of a controlled rollout.
75+
76+
## Example
77+
78+
Unsafe pattern (not allowed):
79+
80+
```sql
81+
ALTER TABLE accounts
82+
ADD CONSTRAINT check_balance CHECK (balance >= 0);
83+
```
84+
85+
Safe pattern (recommended):
86+
87+
```sql
88+
ALTER TABLE accounts
89+
ADD CONSTRAINT check_balance CHECK (balance >= 0) NOT VALID;
90+
```
91+
92+
Validate separately:
93+
94+
```sql
95+
ALTER TABLE accounts
96+
VALIDATE CONSTRAINT check_balance;
97+
```
98+
99+
This ensures the constraint is applied safely without disrupting user traffic.
100+
101+
## Summary
102+
103+
Adding CHECK constraints without `NOT VALID` can block reads and writes and lead to downtime.
104+
This SQL Review rule enforces the two-step PostgreSQL best practice:
105+
106+
* Add the constraint using `NOT VALID`
107+
* Validate it later using a non-blocking operation
108+
109+
By following this pattern, teams can ensure constraint correctness without risking production stability.
29.2 KB
Loading

0 commit comments

Comments
 (0)