PostgreSQL Public 模式的風(fēng)險及安全遷移問題小結(jié)
問題起因
前幾天有群友在群里面咨詢
PG12,13,14,public模式是否可以刪除或改名?
因為這位群友的公司的PG規(guī)范做了修改,不讓使用public模式存放數(shù)據(jù),但是遺留問題沒辦法。
另外一位群友說到
你還真不好動public。擴(kuò)展的插件的函數(shù)大多默認(rèn)都在public 下。
PG中默認(rèn)的public模式帶來的問題
- 安全性問題
public 模式默認(rèn)對所有數(shù)據(jù)庫用戶都開放訪問權(quán)限。換句話說,所有連接到數(shù)據(jù)庫的用戶默認(rèn)都可以訪問 public 模式中的對象(除非你手動修改權(quán)限)。
- 命名沖突
public 模式是所有用戶和所有擴(kuò)展默認(rèn)使用的模式,容易發(fā)生命名沖突。
- 可維護(hù)性和隔離性
使用 public 模式進(jìn)行業(yè)務(wù)操作會使數(shù)據(jù)庫的架構(gòu)設(shè)計顯得雜亂無章,隨著時間推移,尤其是在大型項目或多個項目共享數(shù)據(jù)庫時,public模式中的對象數(shù)量會急劇增加
- 版本和擴(kuò)展的兼容性問題
許多 PostgreSQL 擴(kuò)展默認(rèn)使用 public 模式,如果修改 public 模式或刪除它,可能會導(dǎo)致擴(kuò)展無法正常工作
能否重命名 public 模式
我們能不能通過下面命令對public 模式名重命名 ?
ALTER SCHEMA public RENAME TO you_schema;
實際上重命名 public 模式是不推薦的做法,原因如下
- 依賴性問題:許多擴(kuò)展、插件和默認(rèn)的 PostgreSQL 設(shè)置都假定 public 模式存在。如果直接修改 public 的名稱,會導(dǎo)致這些依賴出現(xiàn)問題。
- 升級問題:未來如果 PostgreSQL 版本升級,系統(tǒng)或新安裝的擴(kuò)展可能仍然依賴于 public 模式存在。
因此,最好的做法是保留 public 模式,但不在業(yè)務(wù)中使用它。
如何解決這個問題
實際上,我們可以使用遷移的方式,新建一個模式,然后把public模式下的所有業(yè)務(wù)對象遷移到新建模式下
具體步驟
第一步:創(chuàng)建新的模式
CREATE SCHEMA employee;
第二步:遷移所有對象:對表、視圖、函數(shù)、存儲過程等對象分別執(zhí)行 SET SCHEMA 操作,將它們從 public 模式遷移到 employee 模式。
遷移對象時小心依賴關(guān)系,如外鍵、索引、函數(shù)依賴等,遷移時需要確保這些依賴關(guān)系不被破壞
使用以下命令逐個遷移:
-- 遷移所有表 ALTER TABLE public.table_name SET SCHEMA employee; -- 遷移所有視圖 ALTER VIEW public.view_name SET SCHEMA employee; -- 遷移所有函數(shù) ALTER FUNCTION public.function_name SET SCHEMA employee; -- 遷移所有存儲過程 ALTER PROCEDURE public.procedure_name SET SCHEMA employee;
使用 SQL 動態(tài)語句和 PL/pgSQL 編寫一個循環(huán)來批量遷移 public 模式中的所有表、視圖、函數(shù)和存儲過程到 employee 模式。
DO $$ DECLARE obj record; BEGIN -- 遷移所有表 FOR obj IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP EXECUTE format('ALTER TABLE public.%I SET SCHEMA employee;', obj.tablename); END LOOP; -- 遷移所有視圖 FOR obj IN SELECT viewname FROM pg_views WHERE schemaname = 'public' LOOP EXECUTE format('ALTER VIEW public.%I SET SCHEMA employee;', obj.viewname); END LOOP; -- 遷移所有函數(shù) FOR obj IN SELECT routine_name, routine_schema FROM information_schema.routines WHERE specific_schema = 'public' LOOP EXECUTE format('ALTER FUNCTION public.%I() SET SCHEMA employee;', obj.routine_name); END LOOP; -- 遷移所有存儲過程 FOR obj IN SELECT routine_name, routine_schema FROM information_schema.routines WHERE specific_schema = 'public' AND routine_type = 'PROCEDURE' LOOP EXECUTE format('ALTER PROCEDURE public.%I() SET SCHEMA employee;', obj.routine_name); END LOOP; END $$;
第三步:設(shè)置 search_path 通過調(diào)整 search_path 讓數(shù)據(jù)庫默認(rèn)使用 employee 模式。
search_path 的設(shè)置順序非常重要。
將 employee 模式放在前面,確保在業(yè)務(wù)操作時優(yōu)先查找 employee 模式的對象,而 public 作為備選模式保留(方便擴(kuò)展和插件的使用)。
可以修改 PostgreSQL 的 postgresql.conf 文件,或者在會話級別設(shè)置 search_path:
SET search_path TO employee, public;
第四步:考慮擴(kuò)展和插件
許多擴(kuò)展和插件默認(rèn)使用 public 模式,例如 PostGIS、pgcrypto 等。
為了避免問題,最好不要修改 public 模式,而是保持其作為擴(kuò)展使用的默認(rèn)模式。
為什么SQL Server 沒有這個問題
SQL Server 沒有像 PostgreSQL 那樣對 public 模式的強烈依賴,并且其設(shè)計理念與 PostgreSQL 的 public 模式存在一些關(guān)鍵區(qū)別。
- 權(quán)限管理的不同
在 SQL Server 中,dbo 是默認(rèn)的 schema,所有數(shù)據(jù)庫用戶默認(rèn)情況下并不會擁有對 dbo 這個 schema 中對象的完全訪問權(quán)限。只有擁有 db_owner 角色的用戶才可以完全控制 dbo 這個 schema。
也就是說,除非用戶顯式授予對 dbo 中對象的訪問或修改權(quán)限,否則,普通用戶是不能隨意訪問或修改 dbo 這個 schema 下的對象的。
相比之下,PostgreSQL 的 public 這個 schema 在默認(rèn)情況下是對所有用戶開放的。這意味著所有用戶都可以在 public 這個 schema 中創(chuàng)建對象,除非手動限制權(quán)限。
PostgreSQL的設(shè)計會增加意外權(quán)限授予和數(shù)據(jù)泄露的風(fēng)險,因此在 PostgreSQL 中有時需要避免使用 public schema。
- 模式設(shè)計理念的不同
在 PostgreSQL 中,public schema 設(shè)計為一個所有用戶共享的默認(rèn)命名空間,因此經(jīng)常發(fā)生命名沖突、權(quán)限管理不嚴(yán)等問題。
在 SQL Server 中,dbo 是為擁有數(shù)據(jù)庫完全控制權(quán)的用戶預(yù)留的默認(rèn)命名空間,通常普通用戶和 DBA 可以自行創(chuàng)建自定義 schema 來組織和隔離各自的數(shù)據(jù)庫對象。
參考文章
https://sdwh.dev/posts/2021/03/SQL-Server-What-Is-dbo/
https://www.ibm.com/support/pages/microsoft-sql-server-tables-get-generated-dbo-schema
https://www.postgresql.org/docs/current/ddl-schemas.html
https://www.crunchydata.com/blog/be-ready-public-schema-changes-in-postgres-15
到此這篇關(guān)于PostgreSQL Public 模式的風(fēng)險以及安全遷移的文章就介紹到這了,更多相關(guān)PostgreSQL Public 模式遷移內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
postgresql 如何查看pg_wal目錄下xlog文件總大小
這篇文章主要介紹了postgresql 如何查看pg_wal目錄下xlog文件總大小的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01PostgreSQL 中的postgres_fdw擴(kuò)展詳解
這篇文章主要介紹了PostgreSQL 中的postgres_fdw擴(kuò)展詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01詳解如何在Ubuntu?18.04上安裝和使用PostgreSQL
關(guān)系數(shù)據(jù)庫管理系統(tǒng)是許多網(wǎng)站和應(yīng)用程序的關(guān)鍵組件,它們提供了一種結(jié)構(gòu)化的方式來存儲、組織和訪問信息,本文演示了如何在?Ubuntu?18.04?VPS?實例上安裝?Postgres,并提供了基本數(shù)據(jù)庫管理的說明,需要的朋友可以參考下2024-07-07在PostgreSQL中使用ltree處理層次結(jié)構(gòu)數(shù)據(jù)的方法
這篇文章主要介紹了在PostgreSQL中使用ltree處理層次結(jié)構(gòu)數(shù)據(jù),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03PostgreSQL 存儲過程的進(jìn)階講解(含游標(biāo)、錯誤處理、自定義函數(shù)、事務(wù))
PL/pgSQL 游標(biāo)允許我們封裝一個查詢,然后每次處理結(jié)果集中的一條記錄,這篇文章主要介紹了PostgreSQL 存儲過程的進(jìn)階介紹(含游標(biāo)、錯誤處理、自定義函數(shù)、事務(wù)),需要的朋友可以參考下2023-03-03常用?PostgreSQL?數(shù)據(jù)恢復(fù)方案及使用示例
這篇文章主要介紹了常用?PostgreSQL?數(shù)據(jù)恢復(fù)方案概覽,數(shù)據(jù)丟失通常是由?DDL?與?DML?兩種操作引起,由于在操作系統(tǒng)中表文件已經(jīng)不存在,所以只能采用恢復(fù)磁盤的方法進(jìn)行數(shù)據(jù)恢復(fù),需要的朋友可以參考下2022-01-01postgresql查詢自動將大寫的名稱轉(zhuǎn)換為小寫的案例
這篇文章主要介紹了postgresql查詢自動將大寫的名稱轉(zhuǎn)換為小寫的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01PostgreSQL基于Citus實現(xiàn)分布式集群的全過程
Citus是一個PostgreSQL擴(kuò)展,它將Postgres轉(zhuǎn)換為分布式數(shù)據(jù)庫,因此您可以在任何規(guī)模上實現(xiàn)高性能,因客戶的需求,本文詳細(xì)闡述了PostgreSQL基于Citus實現(xiàn)的分布式集群的全過程,需要的朋友可以參考下2023-11-11