Diese Seite wurde maschinell übersetzt. Lesen Sie das englische Original. English

IBSurgeon-Bibliothek

Wie bringt man Firebird dazu, viel Speicher zu verbrauchen?

Manchmal haben wir Fälle, in denen der Firebird-Prozess viel RAM verbraucht.

Hier sind 3 Hauptgründe, warum das passiert. Bitte beachten Sie - das sind KEINE Empfehlungen :) Bitte führen Sie sie nicht auf der Produktion aus!

1. Seitenpuffer zu hoch eingestellt

Zum Beispiel für SuperServer in firebird.conf

DefaultDbCachePages = 500000M # pages

Starten Sie Firebird neu und versuchen Sie, sich zu verbinden - das Ergebnis wird die Fehlermeldung “Unable to allocate memory from the operating system” sein:

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>

Das gleiche Ergebnis wird bei vielen Verbindungen mit SuperClassic oder Classic mit einer relativ hohen Anzahl von Seitenpuffern erzielt, gemäß der Formel:

Seitenpuffer X Anzahl der Verbindungen X Seitengröße.

2. Die Größe des Firebird-Prozesses kann aufgrund massiver Operationen mit temporären BLOBs wachsen

Versuchen Sie, das folgende Skript auszuführen (nicht auf der Produktion):

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;

Oder eine andere Variante der Idee

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

Und die folgende Abfrage wird den gesamten Speicher verbrauchen (führen Sie sie nicht auf der Produktion aus!)

select count(*) from blob_loop

3. Für Classic und SuperClassic ist es möglich, die große Anzahl von Seitenpuffern in der Verbindungszeichenfolge von isql.exe anzugeben, und sie wird für diese Verbindung zugewiesen

Wenn Page Buffers nicht explizit auf der Kopfseite gesetzt ist (d.h. gleich 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;

=======