Trang này được dịch bằng máy. Đọc bản gốc tiếng Anh. English

Thư viện IBSurgeon

Làm thế nào để Firebird tiêu tốn nhiều bộ nhớ?

Đôi khi chúng tôi gặp các trường hợp tiến trình Firebird tiêu tốn rất nhiều RAM.

Dưới đây là 3 lý do chính khiến điều này xảy ra. Xin lưu ý - đây KHÔNG phải là các khuyến nghị :) Xin đừng chạy chúng trên môi trường production!

1. Đặt page buffers quá cao

Ví dụ, đối với SuperServer trong firebird.conf

DefaultDbCachePages = 500000M # pages

Khởi động lại Firebird và thử kết nối - kết quả sẽ là thông báo lỗi “Unable to allocate memory from the operating system”:

isql -user SYSDBA -pass masterkey localhost:e:\temp\blob30.fdb Statement failed, SQLSTATE = HY001 unable to allocate memory from operating system -IProvider::attachDatabase failed when loading mapping cache Use CONNECT or CREATE DATABASE to specify a database SQL>

Kết quả tương tự sẽ xảy ra trong trường hợp có nhiều kết nối với SuperClassic hoặc Classic với số lượng page buffers tương đối cao, theo công thức:

Page Buffers X Number of Connections X Page Size.

2. Kích thước tiến trình Firebird có thể tăng lên do các thao tác lớn với BLOB tạm thời

Thử chạy script sau (không chạy trên production):

create generator g1; set generator g1 to 0; execute block as declare variable blb BLOB; declare variable icnt integer; begin icnt=0; while (icnt <100000000) DO begin select cast('1234567890qwertyuiopasdfghjklzxcvbnm' as BLOB) from rdb$database into :blb; select gen_id(g1,1) from rdb$database into :icnt; end end;

Hoặc, một biến thể khác của ý tưởng này

create or alter procedure BLOB_LOOP returns ( ATEXT blob sub_type text ) as begin while (true) do begin atext = '123'; suspend; end end

Và truy vấn sau sẽ ngốn hết bộ nhớ (đừng chạy nó trên production!)

select count(*) from blob_loop

3. Đối với Classic và SuperClassic, có thể chỉ định số lượng page buffers lớn trong chuỗi kết nối của isql.exe, và nó sẽ được cấp phát cho kết nối này

Nếu Page Buffers không được đặt một cách tường minh trong trang header (tức là bằng 0)

`C:\FB\30Cs>echo set list on; set stat on; select mon$page_buffers from mon$database; | isql -c 98765 /:e30 -user foo -pas bar Database: /:e30, User: FOO SQL> MON$PAGE_BUFFERS 98765 Current memory = 869314176 Delta memory = 75760 Max memory = 869334512 Elapsed time= 0.001 sec Buffers = 98765 Reads = 3 Writes = 0 Fetches = 42 SQL>

set bail on; set term ^; execute block as declare n int = 10; declare c int; declare my_password varchar(20) = ‘bar’; begin while (n>0) do begin execute statement ‘select 1 from rdb$database’ on external ’localhost:’ || rdb$get_context(‘SYSTEM’, ‘DB_NAME’) as user current_user password my_password role lpad(’’, 20, replace(uuid_to_char(gen_uuid()),’-’,’’)) into c; n = n - 1;`

end

end

^

set term ;^

set list on;

select count(distinct(t.mon$attachment_id)) as num_of_attachments, sum(t.mon$memory_used) as sum_memo_used, sum(t.mon$memory_allocated) as sum_memo_allocated

from (

select

a.mon$attachment_id

,m.*

from mon$attachments a

join mon$memory_usage m on a.mon$stat_id = m.mon$stat_id

where mon$user = current_user

) t;

=======