1. 程式人生 > 其它 >PostgreSQL 大物件匯出報錯問題分析

PostgreSQL 大物件匯出報錯問題分析

1、前言

在處理使用者問題過程遇到一個問題。使用者通過pg_dump匯出 bytea 物件時,當行的大小超過 1G時,會報錯:

[v8r6c5b41@dbhost01 ~]$ sys_dump -t t1_bytea -f 1.dmp -U system test
sys_dump: error: Dumping the contents of table "t1_bytea" failed: PQgetResult() failed.
sys_dump: error: Error message from server: ERROR: invalid memory alloc request size 1298083843
sys_dump: error: The command was: COPY public.t1_bytea (id1, id2) TO stdout;

我們知道,bytea 型別最大儲存是 1G ,因此,實際的儲存不可能超過1G。 那怎麼會有這個問題了?

2、問題復現

構造兩個二進位制的資料檔案:

[root@dbhost01 dbdata]# ls -l *tar
-rw-r--r-- 1 root root  649041920 May 19 17:15 1.tar
-rw-r--r-- 1 root root 1734932480 May 19 19:12 2.tar

建立測試表:

create table t1_bytea(id1 bytea,id2 bytea) ;

插入資料:

--單個欄位長度超 1G , 報錯
test=# insert into t1_bytea(id1) values(sys_read_binary_file('
/dbdata/2.tar')); ERROR: requested length too large
--單個欄位不超過 1G, 但兩個欄位總大小超過 1G , 報錯。 test
=# insert into t1_bytea values(sys_read_binary_file('/dbdata/1.tar'),sys_read_binary_file('/dbdata/1.tar')); ERROR: invalid memory alloc request size 1298083896
--先insert 單個欄位,再 update 另一個欄位,使得總大小超過 1G , 這種情況下不報錯。 test
=# insert into t1_bytea(id1) values(sys_read_binary_file('/dbdata/1.tar')); INSERT 0 1 test=# update t1_bytea set id2=sys_read_binary_file('/dbdata/1.tar'); UPDATE 1
--insert select 方式不影響 test
=# insert into t1_bytea select * from t1_bytea; INSERT 0 1

驗證匯出資料:

[v8r6c5b41@dbhost01 ~]$ sys_dump -t t1_bytea -f 1.dmp -U system test
sys_dump: error: Dumping the contents of table "t1_bytea" failed: PQgetResult() failed.
sys_dump: error: Error message from server: ERROR:  invalid memory alloc request size 1298083843
sys_dump: error: The command was: COPY public.t1_bytea (id1, id2) TO stdout;

3、結論分析

1、不僅列的大小有 1G 的限制,行的大小也有 1G 的限制;

2、插入資料時,如果一行的資料超過 1G , 則不允許插入;

3、通過 insert 小於 1G 的資料,後續再通過update,可以使得整行資料超過 1G。這也是上述 pg_dump 報錯的根本原因。