Re: BUG #17089: "ERROR: invalid memory alloc request size ..." occurs when updating a fixed number of records

Поиск
Список
Период
Сортировка
От Yuetsuro Kobayashi
Тема Re: BUG #17089: "ERROR: invalid memory alloc request size ..." occurs when updating a fixed number of records
Дата
Msg-id CAL2Sk=TbHYSoQp06oT10rB0M10yYZpDNcyvFzyc7XkKun8XJcg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: BUG #17089: "ERROR: invalid memory alloc request size ..." occurs when updating a fixed number of records  (David Rowley <dgrowleyml@gmail.com>)
Список pgsql-bugs
I still can not understand David's answer.
When I first discovered this "ERROR:  invalid memory alloc request size 1677721600", I realized that this "ERROR" had a lot of hidden column size errors, column overflows, etc., and I've already fixed the bug.
The issue with this "ERROR:  invalid memory alloc request size 1677721600" is that it occurs when you use COPY to repeatedly import multiple CSV files.
The "3,211,154" th record = "1607476406180,150,7.2130" is correct data. And the CSV file containing this record can be imported normally.  This record has only three columns timestamp, ID and number. And all the records are in the same format.
Furthermore, the imported "3,211,154" th record will be correctly imported into the table by COPY.

Look at the execution code that causes "ERROR: invalid memory alloc request size 1677721600" in the code I'm actually processing.
**********************************
--      1st argument : Windows data Starting point directory full path
--      2rd argument : database schema name
CREATE PROCEDURE         scm_exam.import_related_to_prelit ( p1 text, p2 varchar )
AS $$
DECLARE
    argument_absolute_path                          ALIAS FOR p1;
    schema_name                                     ALIAS FOR p2;

    (omit definition...)

BEGIN
    FOR i IN 1..number_of_directory_array LOOP
        directory_name_extraction := directory_name_array[i];
        SELECT scm_exam.check_operationid_directory (directory_name_extraction, schema_name) INTO search_result;
        IF search_result <> 0    THEN CONTINUE;  ELSE END IF;
        current_vehicle_directory_path := argument_absolute_path || '\' || directory_name_extraction;

        -- *** csv file name only extraction
        select array_agg(f) INTO csv_file_name_array from (select f from (select pg_ls_dir(current_vehicle_directory_path) as  f) t where f like '%csv') a;
        IF csv_file_name_array IS NULL  THEN CONTINUE;  ELSE END IF;

        number_of_csvfile_array_count := array_length(csv_file_name_array, 1);
        CASE number_of_csvfile_array_count
        WHEN 0 THEN
            CONTINUE;
        WHEN NULL THEN
            CONTINUE;
        ELSE
        END CASE;

        -- *** for loop 1 .. csv file count ***
        FOR j IN 1..number_of_csvfile_array_count LOOP
            csv_name_extraction := csv_file_name_array[j];
            OPEN prelit_cursor;
            prelit_record_count := COUNT(*) FROM scm_exam.peripheral_information_mtable;
            extracted_csv_file_name := csv_file_name_array[j];
            FOR k IN 1..prelit_record_count LOOP
                -- *** FETCH record from (PRELIT) cursor position
                FETCH prelit_cursor INTO wm_peripheral_inf_id, wm_peripheral_inf_abbreviation_name, wm_temporary_table_name, wm_permanent_table_name;
                IF wm_peripheral_inf_id IS NULL OR wm_temporary_table_name = ''  THEN EXIT;    ELSE END IF;

                -- compare position
                search_result := POSITION( wm_peripheral_inf_id IN extracted_csv_file_name );
                CASE search_result
                WHEN 0 THEN
                    CONTINUE;
                ELSE
                    --*** Obtain the maximum import number before COPY in advance, and set the operation ID in the record of the new import number after creating the table with COPY command.
                    execute_sql = 'SELECT COUNT(*) FROM scm_exam.' || wm_temporary_table_name;
                    EXECUTE execute_sql INTO temp_before_import_record_count;

                    -- copy import
                    current_csv_file_path := current_vehicle_directory_path || '\' || extracted_csv_file_name;
                    exchange_path := '''' || current_csv_file_path || '''';
                    execute_sql := 'COPY scm_exam.' || wm_temporary_table_name || '( w_jst_timestamp, w_id, w_id_value ) FROM ' ||  exchange_path || ' DELIMITERS '','' WITH csv';
                    EXECUTE execute_sql;

                    --*** Obtain the maximum import number before COPY in advance, and set the operation ID in the record of the new import number after creating the table with COPY command.
                    execute_sql = 'SELECT COUNT(*) FROM scm_exam.' || wm_temporary_table_name;
                    EXECUTE execute_sql INTO temp_after_import_record_count;

                    FOR ii IN temp_before_import_record_count+1..temp_after_import_record_count LOOP
                        execute_sql := 'SELECT * FROM scm_exam.' || wm_temporary_table_name || ' WHERE w_serial_no = ' || ii;
                        EXECUTE execute_sql INTO temporary_rec;
                        IF NOT FOUND
                        THEN
                            RAISE WARNING 'PANIC 3900 : % not found import serial number = %', wm_temporary_table_name, ii;
                            RETURN;
                        ELSE
                            IF temporary_rec.w_jst_timestamp != 0 THEN memory_jst_timestamp := temporary_rec.w_jst_timestamp; ELSE END IF;
                            temporary_rec.w_operation_id = '''' || directory_name_extraction || '''';

                            -- Execution code that generates "ERROR: invalid memory alloc request size 1677721600"
                            execute_sql := concat('UPDATE scm_exam.', wm_temporary_table_name, ' SET w_operation_id = ', temporary_rec.w_operation_id, ', w_jst_timestamp = ', memory_jst_timestamp,
                                                   ', w_id = ', temporary_rec.w_id, ', w_id_value = ', '''' || temporary_rec.w_id_value || '''', ' WHERE w_serial_no = ', ii);
                            EXECUTE execute_sql;
                        END IF;
                    END LOOP;
                    EXIT;
                END CASE;
            END LOOP;
            CLOSE prelit_cursor;
        END LOOP;
    END LOOP;
    RETURN;
END;
$$
LANGUAGE 'plpgsql'
**********************************
The import process is called from the parent function by every time the directory changes, and the import is executed with four FOR statements.
  (1) The first FOR statement extracts multiple CSV file names in the directory as an array.
  (2) The second FOR statement retrieves one CSV file name from the array.
  (3) The third FOR statement retrieves the temporary table name registered in the master table and imports the CSV file into the temporary table with "COPY".
  (4) The fourth FOR statement supplements the first column data (timestamp) of the table imported by "COPY" and UPDATEs it.

I'm new to PostgreSQL and I think I'm inexperienced and can't understand you.
Please let me know so that I can understand.

2021年7月8日(木) 22:48 David Rowley <dgrowleyml@gmail.com>:
Please keep the list CC'd

On Thu, 8 Jul 2021 at 19:55, 小林優悦郎 <inconvenience.notice@gmail.com> wrote:
>
> I'm not understand David's answer.
> Why does the UPDATE process succeed when I import only a CSV file that contains the 776,558,539th record information that causes an "ERROR: invalid memory alloc request size 167772160" and perform the UPDATE process?
>     1st directory : xxx_1 (1 - 5,671,588 record)
>     2nd directory: xxx_2 (1 - 4,917,081 record)
>         ...
>     13th directory: xxx_13 ( 1 - ... ERROR by 3,211,154th record)

You should look at that record and see if any fields are unusually
larger than the others.   Types like text, bytea and arrays of types
all have a size limit of 1 Gigabyte in PostgreSQL (internally named
MaxAllocSize).   Going by your original post, in the error message
your receiving, it seems that something is asking for 1677721600
bytes, which is about 1.6GB. Since that's larger than the 1GB limit,
you're getting an error.

You need to look at your data and statements and figure out what might
attempt to store a field that size in the database.

David

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: BUG #17095: ./configure fails thread_test.c when run under TSAN
Следующее
От: PG Bug reporting form
Дата:
Сообщение: BUG #17096: Cannot reinstall after uninstalling PostgreSQL on Windows 10 Pro for Workstations