pondělí 18. února 2019

Proč byla v Nahlížení do KN neaktuální data

Na Twitteru jsem slíbil, že napíši něco k problému, díky kterému byla na Nahlížení do KN  (dále jen Nahlížení) neaktuální data. Ostřílené Oraclisty prosím o shovívavost, protože jsem v rámci čtivosti občas něco zjednodušil.

Pokud čirou náhodou Nahlížení neznáte, tak se ve zkratce jedná o www aplikaci, ve které můžete získat vybrané údaje týkající se vlastnictví parcel, staveb, jednotek evidovaných v katastru nemovitostí, informace o stavu řízení a další užitečné informace.  

Architektura replikací

Nahlížení má svoji samostatnou databázi, do které se replikují data z interní databáze ISKN:

Replikuje se cca 200 databázových tabulek, replikace probíhají každé 2 hodiny a jsou založeny na Oracle Materialized View. Pro zachování logické konzistence dat a cizích klíčů (Foreign Key) jsou všechny tabulky umístěny v jedné  replikační skupině (Materialized View Group), což znamená, že se v rámci jednoho průběhu replikací musí úspěšně zreplikovat všechny tabulky v dané skupině, jinak replikace zhavarují. Takže systém vše nebo nic. 
Pozn.: ve skutečnosti je replikační model košatější. Replikačních skupin tam mámě několik, včetně opačného směru, a ještě se do Nahlížení replikují data z databáze ISÚI.

Kódové stránky

Další věc, která je v tomto případě podstatná, je tzv. character set databáze, což je zjednodušeně řečeno kódová stránka. Protože v době vzniku ISKN nebyla v Oracle rozumná podpora pro Unicode, tak databáze ISKN využívá EE8ISO8859P2 se single-byte  kódováním (každý znak je uložen právě v jednom byte). 
Nahlížení je novější a využívá character set AL32UTF8, což odpovídá Unicode ve verzi 6.2 a je doporučován samotným Oracle. Tento character set je vícebytový (Multibyte) a využívá proměnnou délku kódování (Variable-width encoding), kdy je každý znak podle potřeby uložen v 1-4 byte.  
Pozn 1.: české znaky se tuším vejdou do 2 byte, ale ruku do ohně za to teď nedám.
Pozn 2.: jsou i Multibyte kódování s pevnou délkou, např. UTF-32.

V Oracle se velikost sloupců pro ukládání textu (typicky VARCHAR2) dá definovat dvěma způsoby - v bytech nebo znacích (Char). Velikost v bytech je maximální počet byte, které do sloupečku půjdou uložit, velikost ve znacích udává maximální počet znaků.

V Singlebyte databázi (EE8ISO8859P2) je to jedno, ale v Multibyte (AL32UTF8) je to podstatné, protože do sloupečku s definicí "VARCHAR2 9 Byte" nejde vložit řetězec "nahlížení", neboť má sice jen 9 znaků, ale jeho skutečná reprezentace má délku 12 byte (3 byte navíc jsou díky 3 českým znakům, každý je reprezentován 2 byte). Proto je v obou databázích  ISKN a Nahlížení použita definice pomocí znaků (Char), což eliminuje problém s rozdílnou délkou skutečného uložení řetězců.

Vznik chyby a její příčina

V pátek 8.2.2019 nám dopoledne začal systém indikovat, že se nedaří provést replikace z ISKN do Nahlížení. Replikace končily na chybu:

ORA-12008: error in materialized view or zonemap refresh path
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2952
ORA-06512: at "SYS.DBMS_SNAPSHOT_KKXRCA", line 2370
ORA-12899: value too large for column "ISKN"."AK_JINE_PRAV_VZTAHY"."POPIS_PRAVNIHO_VZTAHU" (actual: 4379, maximum:
4000)

Jednalo se o sloupec tabulky AK_JINE_PRAV_VZTAHY, do kterého se ukládá popis jiného právního vztahu a který je v obou databázích definován shodně, jak délka 4000, tak jednotky Char: 
SQL> desc AK_JINE_PRAV_VZTAHY
Name                    Type
---------------------------------------
ID                      NUMBER(30)
VERZE                   NUMBER(30)
OPSUB_ID_K              NUMBER(30)
TYPRAV_KOD              VARCHAR2(4 CHAR)
POPIS_PRAVNIHO_VZTAHU   VARCHAR2(4000 CHAR)
TEL_ID                  NUMBER(30)
(zkráceno...)

V ten okamžik jsme začali jsme tušit větší problém. Po detailním trasování jsme zjistili, že problém dělá řádek, který má v ISKN délku 3963 znaků a měl by se tedy do 4000 znaků v Nahlížení, kde jeho velikost díky českým znakům v AL32UTF8 naskočila na 4379 byte, s rezervou vejít. 

Zapojili jsme do pátrání i pracovníky podpory české pobočky Oracle a ti po dalším zkoumání přišli s tím, že Oracle sice povolí pro datový typ VARCHAR2 použít maximální velikost 4000 Char, ale ve skutečnosti je strop na 4000 byte, bez ohledu na použití jednotky char. Je to interní limit, což je v případě vícebytového AL32UTF8 docela průšvih. 

Zrádné je to navíc v tom, že se na limit narazí, až pokud se blíží oné maximální velikosti 4000. Pokud je sloupec definován jako "VARCHAR2 500 CHAR", tak se do něj v AL32UTF8 bez problémů 500 českých znaků uloží, přestože zabírají například 560 byte. V našem případě byla velikost problémového záznamu v ISKN (Singlebyte EE8ISO8859P2) 3963 znaků, ale po přenosu do Nahlížení se díky Multibyte AL32UTF8 zvětšila na 4379 byte a narazilo se na strop 4000 byte.

Hledání řešení

Možných řešení bylo několik.

1) Změna character set databáze

Character set se v Oracle definuje při vytváření databáze a následně jíž nejde jednoduše změnit. Je potřeba vytvořit databázi novou, přeexportovat data atd. Je šílená práce, která by v případě Nahlížení trvala několik dnů (export dat, nová databáze, import dat, vše znovu nastavit atd) a musela by se ještě předem důkladně vyzkoušet. 
Existují sice nějaké neoficiální postupy jak to změnit, ale to si nemůžeme u takového systému jen tak dovolit. V Oracle 12c se také objevil oficiální nástroj Database Migration Assistant for Unicode, pomocí kterého by měl jít character set změnit, ale od jeho použití nás v produkčním prostředí odrazovali samotní pracovníci Oracle, protože je (zatím) velmi problémový a plný chyb. Vše by se muselo nejprve vyzkoušet na kopii databáze a ani tak by jistota funkčnost nebyla a navíc jsme nechtěli přecházet z Unicode zpět.

2) Změna parametru max_string_size

Další možností bylo změnit parametr max_string_size na hodnotu "extended", což zvýší limit ze 4000 byte na 32767 byte, což by bohatě stačilo:
STARTUP UPGRADE;
ALTER SYSTEM SET max_string_size=extended;
@?/rdbms/admin/utl32k.sql
SHUTDOWN IMMEDIATE;
STARTUP;

Jenže je zde obdobný problém jako u předchozího řešení. Po dlouhém zkoumání opět samotný Oracle tento postup nedoporučil, protože součástí změny je nutnost spustit script utl32k.sql pro úpravu Oracle Dictionary (katalog - interní tabulky popisující strukturu samotné databáze), na který v Oracle Supportu zrovna chvála není:

Důsledkem by také byla byla fragmentace řetězců v databázi. Zároveň bychom museli změnit inicializačního parametr "compatible", který mám vliv i na chování CBO optimalizátoru dotazů. takže to není bez důkladného testování možné. Opět tedy několik dnů testování a zkoušení, navíc s nejistým výsledkem.

Pozn.: Pokud by databáze byla vytvořena přímo s parametrem max_string_size nastaveným na extended, tak by odpadl problém s fragmentací řetězců a nemusel by se spouštět script utl32k.sql. To je ale jen teoretická možnost, protože to znamená vytvořené nové databáze, viz předchozí řešení 1). Navíc jsme od pracovníků podpory Oracle dostali následující informaci:
"ani po delším pátrání se mi nepodařilo najít reference na použití max_string_size = extended. To znamená, že nemůžeme vyloučit komplikace, bugy apod.".

3) Redefinice MVIEW AK_JINE_PRAV_VZTAHY

Jako jednoduché řešení se nabízelo vytvořit v Nahlížení znovu Materialized View pro dotčenou tabulku AK_JINE_PRAV_VZTAHY  tak, že by se problémový sloupec rozdělil na dvě části, každá o velikosti 4000 CHAR. Reálně by se tedy, díky limitu, do každé části vešlo až 2000 českých znaků, celkem 4000 znaků, což je maximum, které lze v ISKN zapsat:
create mview as 
select id,
substr(popis_pravniho_vztahu,1,2000) as popis_pravniho_vztahu, substr(popis_pravniho_vztahu,2001) as popis_pravniho_vztahu_1,
…. from ak_jine_prav_vztahy@iskni 

To však narazilo z více důvodů. Prvním důvodem byla nutnost upravit aplikaci, která by musela interně oba sloupce zase zpět spojovat. To by nějakou dobu zabralo, ale asi by to šlo za víkend provést a otestovat (+ předělat  MVIEW, i to nějakou dobu trvá, protože by se musela znovu přenést všechna data). 

Druhý důvod byl závažnější. V Nahlížení je na replikované tabulky navázáno přes databázové triggery hlídání přicházejících změn, na jejichž základě se následně provádějí další změny v grafické části (mapě). Novou definicí MVIEW bychom tedy přišli o možnost zpracovat o změny, které v tu dobu již byly nachystané v replikační frontě v ISKN a příslušná část grafiky by se musela kompletně od začátku znovu spočítat, což je časově velmi náročná akce (dny) a navíc jsme neměli vyzkoušen postup, kdy se přepočte jen jedna část. 

4) Aplikační úprava problémového textu v ISKN

Toto řešení by spočívalo v tom, že by se v ISKN upravil problematický text tak, aby se i s českými znaky v Nahlížení vešel do 4000 byte. Použil by se standardní postup přes aplikaci ISKN, jako každá jiná změna v ISKN. Takže založit řízení a provést aktualizaci dat se vším, co k tomu formálně patří. To by ale znamenalo čekat až do pondělí, protože o víkendu nikoho z daného katastrálního pracoviště, které daný jiný právní vztah zapsalo, neseženeme, a do práce nenaženeme.

Následně jsme si ale uvědomili, že bychom tím problém vlastně nevyřešili. Datový model ISKN je navržen takovým způsobem, aby bylo možné zjistit stav data k jakémukoli času. Proto je možné dělat např. výpisy KN k zpětně. Funguje to tak, že pro každou entitu (jiný právní vztah, parcela, stavba, ...) existují 3 tabulky:

  • AK_JINE_PRAV_VZTAHY
  • AK_JINE_PRAV_VZTAHY_B
  • AK_JINE_PRAV_VZTAHY_M

Tabulka AK_JINE_PRAV_VZTAHY (bez suffixu) slouží k uložení aktuálně platných dat, tzv. přítomnost.
Tabulka AK_JINE_PRAV_VZTAHY_B (budoucnost) slouží k vytváření budoucího stavu dat, který bude platit po tzv. zplatnění řízení (navrhují se v ní změny dat).
Tabulka AK_JINE_PRAV_VZTAHY_M (minulost) slouží k uložení již neplatných dat a využívá se právě pro zpětné výpisy, zjištění vývoje změn atd.

Zaměstnanec při zápisu změny navrhne v _B tabulce stav, jak by data měla vypadat. Poté proběhne kontrola jiným pracovníkem a pokud je úspěšná, tak se provede zplatnění řízení, což znamená, že se z přítomnostní tabulky (bez suffixu) data přesunou do minulostní (suffix _M) a z budoucnosti (suffix _B se přesunou do přítomnosti).
Z toho plyne, že bychom aplikační aktualizací problém s délkou textu jen přesunuli z tabulky pro přítomnost (AK_JINE_PRAV_VZTAHY) do tabulky pro minulost (AK_JINE_PRAV_VZTAHY_M).

Pozn.: Rozdělení na 3 tabulky a ne např. použitím atributu v jedné tabulce je dáno historicky. Bylo na zvoleno začátku tvorby ISKN (1997) pro optimalizaci výkonu, protože většina dotazů je na přítomnost, která oddělením od minulosti není velká. 
V ISKN se následně pro přístup využívají tzv. Partitioned views, což v současné době není doporučované technika a působí problémy při migraci na vyšší verze (zhavaroval na ní pokus o přechod na Oracle 11, protože se k takovýmto view přistupuje přes opět hodně zabugovaný JPPD).  Aktuálně se v rámci migrace na Oracle 12c připravuje změna založena na sloučení těchto 3 tabulek do jedné s využitím Oracle Partitioningu, což udělá docela vítr v datovém modelu a celé aplikaci, ale je to koncepční řešení.

5) Úprava problémového textu v ISKN na úrovni databáze

Protože jsme administrátoři, tak můžeme provést update záznamu na úrovni databáze. pomocí SQL příkazu. Jenže to si nemůžeme jen tak dovolit. Někdo ten záznam vytvořil, je za jeho obsah odpovědný a my bychom mu to změnili. Záznam vznikl na základě nějaké listiny, která byla doručena spolu s  návrhem na vklad. Zasáhnout do zapsaného textu není tak jednoduché a mohlo by to znamenat problém, přestože bychom to provedli v dobré víře zprovoznění replikací.

Problém je v tom, že změna by se projevila nejen v Nahlížení, ale i v ISKN, ze kterého pracovníci vydávají veřejné listiny, a také ve výstupech Dálkového přístupu, které mají také charakter veřejné listiny a jsou opatřeny kvalifikovanou pečetí.

Další komplikací by mohlo být, pokud by někdo v rozmezí od okamžiku zápisu daného textu v ISKN do provedení této "tvrdé" opravy na úrovni databáze získal Výpis z KN,  ať už z Dálkového přístupu nebo na přepážce, případně by odebral data ve výměnném formátu nebo jako geodet přes WS GP. Pokud bychom do textu sáhli takto natvrdo, mimo aplikační logiku, tak by se při vyhotovení výpisu ke zpětnému časovému okamžiku toulaly po světě dva výpisy z KN s platností ke stejnému časovému okamžiku, ale s jinými texty. U výměnného formátu bychom zase porušili logiku změnových vět.

Ačkoli by tedy technicky tato změna byla jednoduchá (jeden SQL příkaz), tak z formálního hlediska zase tak jednoduchá není.  

Řešení 

Nějak jsme situaci ale vyřešit museli. Replikace stály už více jak 24 hodin, což není dobré ani pro uživatele, ani pro systém, protože se hromadí data v replikačních frontách a následné spuštění replikací je o to delší.

Varianty 1) a 2) byly hodně rizikové. Komplikuje je také fakt, že v databázi  s replikacemi se nemůžete jen tak v případě problémů vrátit v čase zpět. Kdyby se nějaký problém objevil po tom, co by úspěšně do Nahlížení proběhly replikace z ISKN nebo ISÚI, tak už by se nešlo vrátit zpět a následně zkusit jiné řešení, protože by se replikace rozsynchronizovaly (v ISKN nebo ISÚI  by byla data, která by se tvářila, že už jsou zreplikovaná i v Nahlížení, ale tam by díky vrácení v čase se zpět nebyla). Data by se musela  přenést všechna znovu (provést tzv. complete refresh, který přenese vše, ne pouze fast refresh, který přenáší jen změny). Complete refresh je na dlouho a ještě komplikovaný tím, že ve zdrojové databázi (ISKN, ISÚI) nesmí v tu dobu pro aktuálně přenášení MVIEW probíhat žádné změny. Následně by se v Nahlížení musela kompletně znovu spočítat grafika, viz konec bodu 3). V neposlední řadě bychom vrácením se zpět také přišli o všechna data pořízení přímo v Nahlížení.

Varianta 3) by sice byla funkční a bez problémů, ale časově velmi náročná (dny) a řešila by jen jednu tabulku. Varianta 4) by nepomohla a tak nám po dlouhém zvažování (pořád jsme přemýšleli nad 1) a 2) ) zbyla varianta 5).

Varianta 5) také nebyla ideální, nicméně jsme se pro ni rozhodli s tím, že nám umožní vyřešit co nejrychleji aktuální problém a získáme čas na provedení koncepčního řešení.

Přemýšleli jsme, co s tím, jak změnit text, aby z toho nebyl problém. Nakonec jsme se rozhodli, že zkusíme jen odstranit diakritiku. Nejprve jsme zkontrolovali, že se odstraněním diakritiky nijak nezmění význam textu. Pak jsme prověřili vydané výpisy, výstupy výměnného formátu atd., viz popis ve variantě 5). Naštěstí proběhl jen relativně krátký časový okamžik a ještě to bylo v pátek. Odešlo sice vyrozumění o zápisu daného řízení a s ním výpis, ale to je kontrolovaný a podchycený proces. Do karet nám také hrál fakt, že se by se "jen" odstranila diakritika, takže i kdyby byl výpis vydaný, nebyl by to takový průšvih, nicméně příjemné by to nebylo.

Museli jsme také ověřit, že daným zásahem nezpůsobíme nějakou aplikační nekonzistenci. Některé akce v ISKN jsou hlídány přes databázové triggery a jejich nové spuštění by mohlo vyvolat např. duplicity v navázaných datech atd.

Po prověření jsme požádali vedení o schválení provedené této "tvrdé" úpravy přímo v databázi a po vysvětlení situace, našich zjištění a možných řešení jsme obdrželi souhlas. Zazálohovali jsme tedy měněný záznam a provedli jeho aktualizaci jednoduchým příkazem:
update ak_jine_prav_vztahy set
popis_pravniho_vztahu=convert(popis_pravniho_vztahu,'US7ASCII')
where id=1234

Za dalších 30 minut už všechny replikace na Nahlížení úspěšně proběhly. 

Závěr

Řešení tedy bylo triviální a otázka 5 sekund. Než jsme k němu ale dospěli, tak to trvalo 1.5 dne (1/2 pátku a sobotu) perné práce, protože jsme museli zkoumat možné varianty, ověřovat je atd.

Není to ale řešení trvalé a teď zvažujeme co dál. Naštěstí pravděpodobnost, že by se situace mohla opakovat velká není (délka textu byla opravdu extrémní). Do definitivního vyřešení jsme přijali i organizační opatření. Zatím váháme, zda se v rámci připravovaného cross-platform upgrade (v rámci konsolidace prostředí přechod databáze Nahlížení z Linuxu na AIX) pustit do řešení podle poznámky v bodu 2), které by bylo sice systémovější, ale s možnými problémy, nebo zda půjdeme řešením 3) a sloupec (vlastně sloupce, celkem takových s VARCHAR2(4000) máme v různých tabulkách 4) v Nahlížení rozdělíme na 2. Pokud bychom to dělali řízeně, s prázdnou replikační frontou, tak bychom nepřišli o žádné změny a nebylo by nutné přepočítávat grafickou část.



Pár zajímavostí a poznámek pod čarou


1) Kdybychom nebyli "pokrokoví" a databází Nahlížení udělali také v Singlebyte kódování a nikoli Unicode s proměnnou délkou, tak jsme si tyto problémy ušetřili, obzvláště v kombinaci s replikacemi databází databází s různým character set.

2) Pokud vás zajímá, na čem ztroskotal náš předchozí pokus o upgrade ISKN na Oracle 11g nebo  problematika Partiton Views zmíněná v řešení 3) s bugy JPPD, tak si přečtete naši podrobnou analýzu. Výživné a velmi poučné čtení.

3) Chyba "ORA-12899: value too large for column"  se při replikacích začala objevovat až po nedávné migraci (prosinec 2018) databáze Nahlížení na Oracle 12.2. Ten samý problém ale byl i v předchozích verzích, jenže Oracle při replikacích chybu nehlásil, ale data prostě bez jakéhokoli upozornění ořezal, což je ještě horší.

4) Tvrdým limitem 4000 byte pro VARCHAR2 byli překvapení i samotní pracovníci podpory Oracle. Nemohli ve svých interních systémech dohledat hlášený obdobný problém, což zase překvapilo nás. Zřejmě se kombinace tak dlouhých VARCHAR2 položek v kombinaci s proměnnou délkou kódování a znaky, které se nevejdou do 1 byte, tak často neobjevuje a používá se spíše CLOB.

5) Chování Oracle při použití Multibyte s proměnnou délkou (Nahlížení, AL32UTF8) je opravdu zákeřné, příklad:
(funkce length(rpad('X',4000,'X')) doplní řetězec "X" až do délky 4000 znaků dalšími "X")

SQL> select length(rpad('X',4000,'X')) as delka from dual;
DELKA
--------------------------
                      4000 (očekávaný výsledek)

Když místo US znaku X použijete znak český, tak najednou dostanete pouze 2000 znaků (reprezentovaných 4000 byte): 

SQL> select length(rpad('Ň',4000,'Ň')) as delka from dual;
DELKA
--------------------------
                      2000 

Pro mě neočekávaný výsledek, který je daný tím, že interní reprezentace v rámci implicitního kurzoru pro 2000 českých znaků je v Multibyte 4000 byte a Oracle to prostě na 2000 znacích bez uzardění ořízne. Když ten samý dotaz spustíte v Singlebyte databázi (ISKN, EE8ISO8859P2), tak je vše OK:

SQL> select length(rpad('Ň',4000,'Ň')) as delka from dual;
DELKA
--------------------------
                      4000 

Dotaz vypadá nevinně a různý výsledek v různých databázích docela zaskočí. Na takových věcí pak narazíte spousty, pokud už víte, co hledat. 

6) V dokumentaci Oracle se píše: 
The VARCHAR2 datatype stores variable-length character strings. When you create a table with a VARCHAR2 column, you specify a maximum string length (in bytes or characters) between 1 and 4000 bytes for the VARCHAR2 column
Je to zavádějící a jak jsem psal, překvapilo to i samotné pracovníky Oracle. Tohle vám prostě nedocvakne, když o tom nevíte. O nutnosti používat v Multibyte jednotky Char jsme věděli (narazili jsme na to v replikacích již dříve u kratších polí), ale o tvrdém limitu 4000 byte při použití Char ne. Chtělo by to velké červené varování.

7) Z mého textu mohlo zdát, že Oracle je ten nejvíce zabugovaný SW na světě a je prakticky nepoužitelný. Přesto si myslím, že Oracle je v oblastí SQL databází špička, daleko před ostatními (např. technologie RAC), a jinou databází bychom si nijak nepolepšili. Bugy jsou všude a u nás většinou bohužel narazíme na nějaké speciality, které se jinde neřeší. Navíc český support se opravdu snaží. Ale je pravda, že si Oracle jak za licence, tak služby supportu, nechá řádně zaplatit.

8) K druhé větě v odstavci Řešení - někteří uživatelé jsou tak nedočkaví, že se občas stane situace, že náš zaměstnanec zplatní řízení a než připraví a odešle účastníkům řízení vyrozumění o zápisu (to jde i Datovou schránkou), tak se data stihnou zreplikovat na Nahlížení (replikace mohou proběhnout třeba za 5 minut), kde si uživatelé hlídají jejich řízení/LV a volají našemu zaměstnanci, kdy si mohou přijít pro výsledek atd. :-)

středa 13. února 2019

Pozor na KeePass

KeePass je jeden z často používaných správců hesel, který je uvolněný pod General Public Licencí veze 2.

Na rozdíl od různých cloudových správců funguje tak, že máte hesla uložené v jeho "databázi" (soubor), ke které získáte přístup po zadání hlavního klíče ("master password") nebo např. použitím souboru klíče v souboru ("Key File"). Způsobů existuje více.


Tento nástroj má implementovanou jednu vlastnost, na kterou mě dnes upozornil kolega Jirka V. Publikoval jsem ji na Twitteru, ale pak jsem usoudil, že si zaslouží samostatný článek.

V jeho konfiguraci lze nastavit tzv. triggery, což jsou události, které se spustí při určité akci. Na tuto událost lze pak provést další akce.  Jednou z událostí je i otevření/odemčení databáze s hesly a jednou z akcí je export této databáze. Stačí do KeePass.config.xml dopsat níže uvedenou část a při každém odemčení se současně databáze vyexportuje do souboru c:\temp\hesla.txt:

<TriggerSystem>
  <Enabled>true</Enabled>
  <Triggers>
    <Trigger>
      <Guid>esN+2TpQpUSxHM2rzGhXmw==</Guid>
      <Name>test</Name>
      <Events>
        <Event>
          <TypeGuid>5f8TBoW4QYm5BvaeKztApw==</TypeGuid>
          <Parameters>
            <Parameter>0</Parameter>
            <Parameter/>
          </Parameters>
        </Event>
      </Events>
      <Conditions/>
      <Actions>
        <Action>
          <TypeGuid>D5prW87VRr65NO2xP5RIIg==</TypeGuid>
          <Parameters>
            <Parameter>c:\temp\hesla.txt</Parameter>
            <Parameter>KeePass CSV (1.x)</Parameter>
            <Parameter/>
            <Parameter/>
          </Parameters>
        </Action>
      </Actions>
    </Trigger>
  </Triggers>
</TriggerSystem>

V domácím použití to není úplně kritické, protože pokud se vám někdo dostane do počítače, aby vám bez vašeho vědomí změnil konfigurační soubor KeePass.config.xml, tak máte velký problém tak jak tak. Horší je ale, pokud je KeePass používán ve firemním prostředí jako úložiště hesel pro více uživatelů, což je scénář, který KeePass přímo podporuje a uvádí.  

Představme si tedy scénář, kdy je databáze s hesly uložena na sdílení a přístup k ní mají jen oprávnění uživatelé, mezi které ale nepatří administrátor systému, na kterém je databáze a konfigurace uložena. Když takový administrátor do konfigurace doplní výše uvedenou část, tak stačí, aby někdo jiný (oprávněný), otevřel databázi s hesly, na což zareaguje trigger a spustí export hesel do textového souboru. V podstatě ji dostane naservírovanou na talíři. 

Pozor tedy na tuto (dokumentovanou) vlastnost, není to chyba. Jen mám pochybnosti, zda je tato vlastnost ve všeobecné známosti uživatelů, kteří KeePass používají. Já KeePass nepoužívám a nevěděl jsem o tom, ale i kdybych ho používal, tak upřímně, zase tak detailně nápovědu a možnosti konfigurace nestuduji a určitě bych o tom nevěděl.

Možná je čas se poohlédnout po nějakém jiném řešení, obzvláště v podnikovém prostředí. Inspirovat se můžete třeba na následujících stránkách:
https://smallbiztrends.com/2018/01/best-password-manager-apps-small-business.html

Na závěr přidávám doplnění od Michala Špačka, uznávaného odborníka na bezpečnost:
Asi je dobré poznamenat, že dávat do firemního správce hesel "nefiremní" přístupy, kde by vadilo, že se k nim dostane např. správce, který nakonfiguruje triggery, není dobrý nápad a ani dokumentace KeePassu takovou věc nezmiňuje. Zákeřný admin systému se k heslům v databázi vždy dostane, triggery, netriggery.