{"id":72265,"date":"2020-03-03T08:42:17","date_gmt":"2020-03-03T05:42:17","guid":{"rendered":"https:\/\/prohoster.info\/blog\/postgresql-antipatterns-menyaem-dannye-v-obhod-triggera"},"modified":"2020-03-03T16:13:51","modified_gmt":"2020-03-03T13:13:51","slug":"postgresql-antipatterns-menyaem-dannye-v-obhod-triggera","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/postgresql-antipatterns-menyaem-dannye-v-obhod-triggera","title":{"rendered":"PostgreSQL Antipatterns: \u00c4ndern von Daten \u043e\u0431\u0445\u043e\u0434 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Fr\u00fcher oder sp\u00e4ter stehen viele vor der Notwendigkeit, in einer Tabelle etwas massenhaft zu korrigieren. Ich habe bereits <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/481610\/\">erz\u00e4hlt, wie man es besser macht<\/a><\/noindex>, und wie \u2014 besser nicht. Heute erz\u00e4hle ich von dem zweiten Aspekt der massiven Aktualisierung \u2014 <b>vom Ausl\u00f6sen von Triggern.<\/b>.<\/p>\n<p>Zum Beispiel h\u00e4ngt an der Tabelle, in der Sie etwas korrigieren m\u00fcssen, ein b\u00f6sartiger Trigger <code>ON UPDATE<\/code>, der alle \u00c4nderungen in irgendwelche Aggregate \u00fcbertr\u00e4gt. Und Sie m\u00fcssen alles aktualisieren (ein neues Feld initialisieren, zum Beispiel) so vorsichtig, dass diese Aggregate nicht ber\u00fchrt werden.<\/p>\n<h2>Lassen Sie uns einfach die Trigger deaktivieren!<\/h2>\n<p><\/p>\n<pre><code class=\"sql\">BEGIN;\n  ALTER TABLE ... DISABLE TRIGGER ...;\n  UPDATE ...; -- hier lange, lange\n  ALTER TABLE ... ENABLE TRIGGER ...;\nCOMMIT;<\/code><\/pre>\n<p>\nEigentlich ist das alles \u2014 <b>alles h\u00e4ngt schon.<\/b>.<\/p>\n<p>Denn <code>ALTER TABLE<\/code> legt <b>AccessExclusive<\/b>-Sperre auf, unter der niemand, der parallel l\u00e4uft, selbst ein einfacher <code>SELECT<\/code>, nichts aus der Tabelle lesen kann. Das hei\u00dft, solange diese Transaktion nicht abgeschlossen ist, werden alle, die \u201ceinfach lesen\u201d wollen, warten m\u00fcssen. Und wir erinnern uns, dass <code>UPDATE<\/code> bei uns sehr lange dauert...<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h4>Lassen Sie es uns also schnell deaktivieren und dann schnell wieder aktivieren!<\/h4>\n<p><\/p>\n<pre><code class=\"sql\">BEGIN;\n  ALTER TABLE ... DISABLE TRIGGER ...;\nCOMMIT;\n\nUPDATE ...;\n\nBEGIN;\n  ALTER TABLE ... ENABLE TRIGGER ...;\nCOMMIT;<\/code><\/pre>\n<p>\nHier ist die Situation bereits besser, die Wartezeit ist erheblich k\u00fcrzer. Aber zwei Probleme tr\u00fcben die ganze Sch\u00f6nheit:<\/p>\n<ul>\n<li><code>ALTER TABLE<\/code> selbst wartet auf alle anderen Operationen in der Tabelle, einschlie\u00dflich langer. <code>SELECT<\/code><\/li>\n<li>Solange der Trigger deaktiviert ist, <b>entkommt jede \u00c4nderung<\/b> in der Tabelle, selbst nicht unsere. Und sie wird auf keinen Fall in die Aggregate gelangen, obwohl sie sollte. Das ist ein Problem!<\/li>\n<\/ul>\n<p><\/p>\n<h2>Verwaltung von Sitzungsvariablen<\/h2>\n<p>\nNun, im vorherigen Beispiel sind wir auf einen prinzipiellen Punkt gesto\u00dfen \u2014 wir m\u00fcssen die Trigger irgendwie lehren, \"unsere\" \u00c4nderungen in der Tabelle von \"nicht unseren\" zu unterscheiden. \"Unsere\" lassen wir unber\u00fchrt, und die \"nicht unseren\" sollten ausgel\u00f6st werden. Dazu k\u00f6nnen wir <noindex><a rel=\"nofollow\" href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/runtime-config-client\">Sitzungsvariablen<\/a><\/noindex>.<\/p>\n<h4>session_replication_role<\/h4>\n<p>\nLesen Sie <noindex><a rel=\"nofollow\" href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/sql-altertable\">das Handbuch<\/a><\/noindex>:<\/p>\n<blockquote><p>Auch die Ausl\u00f6semechanismen der Trigger werden von der Konfigurationsvariablen beeinflusst <noindex><a rel=\"nofollow\" href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/runtime-config-client#GUC-SESSION-REPLICATION-ROLE\">session_replication_role<\/a><\/noindex>. Trigger, die ohne zus\u00e4tzliche Angaben (standardm\u00e4\u00dfig) aktiviert werden, l\u00f6sen sich aus, wenn die Replikationsrolle \u2014 \"origin\" (standardm\u00e4\u00dfig) oder \"local\" ist. Trigger, die durch die Angabe <code>ENABLE REPLICA<\/code>aktualisiert wurden, l\u00f6sen sich nur aus, wenn <b>der aktuelle Sitzungsmodus<\/b> \u2014 \"replica\" ist, und Trigger, die durch die Angabe <code>ENABLE ALWAYS<\/code>, l\u00f6sen sich unabh\u00e4ngig vom aktuellen Replikationsmodus aus.<\/p><\/blockquote>\n<p>Ich m\u00f6chte besonders betonen, dass die Einstellung nicht f\u00fcr alle gleichzeitig gilt, wie <code>ALTER TABLE<\/code>, sondern nur zu unserem speziellen Einzelverbindung. Insgesamt, um zu verhindern, dass irgendwelche Anwendungstrigger aktiv werden:<\/p>\n<pre><code class=\"sql\">SET session_replication_role = replica; -- Trigger deaktiviert\nUPDATE ...;\nSET session_replication_role = DEFAULT; -- wieder in den urspr\u00fcnglichen Zustand versetzt<\/code><\/pre>\n<p><\/p>\n<h4>Bedingung innerhalb des Triggers<\/h4>\n<p>\nAber die oben angegebene Variante funktioniert f\u00fcr alle Trigger gleichzeitig (oder man muss im Voraus die Trigger \"altern\", die man nicht deaktivieren m\u00f6chte). Und wenn wir <b>\u201eeinen bestimmten Trigger deaktivieren\u201c<\/b>?<\/p>\n<p>Dabei hilft uns <noindex><a rel=\"nofollow\" href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/runtime-config-custom\">\u201ebenutzerdefinierte\u201c Sitzungsvariable<\/a><\/noindex>:<\/p>\n<blockquote><p>Die Namen der Erweiterungsparameter werden folgenderma\u00dfen geschrieben: Name der Erweiterung, Punkt und dann der Name des Parameters, \u00e4hnlich wie die vollst\u00e4ndigen Namen der Objekte in SQL. Zum Beispiel: plpgsql.variable_conflict.<br \/>\nDa eventdata-spezifische Parameter in Prozessen gesetzt werden k\u00f6nnen, die das entsprechende Modulpaket nicht laden, akzeptiert PostgreSQL <b>Werte f\u00fcr beliebige Namen mit zwei Komponenten<\/b>.<\/p><\/blockquote>\n<p>Zuerst \u00fcberarbeiten wir den Trigger, ungef\u00e4hr so:<\/p>\n<pre><code class=\"sql\">BEGIN\n    -- Im Konvertierungsprozess kann alles gemacht werden\n    IF current_setting('mycfg.my_table_convert_process') = 'TRUE' THEN\n        IF TG_OP IN ('INSERT', 'UPDATE') THEN\n            RETURN NEW;\n        ELSE\n            RETURN OLD;\n        END IF;\n    END IF;\n...<\/code><\/pre>\n<p>\n\u00dcbrigens kann man das \u201elive\u201c, ohne Sperren, \u00fcber <code>CREATE OR REPLACE<\/code> f\u00fcr die Triggerfunktion. Und dann setzen wir in der speziellen Verbindung \u201eunsere\u201c Variable:<\/p>\n<pre><code class=\"sql\">\nSET mycfg.my_table_convert_process = 'TRUE';\nUPDATE ...;\nSET mycfg.my_table_convert_process = ''; -- zur\u00fcck in den urspr\u00fcnglichen Zustand versetzt\n<\/code><\/pre>\n<p>\nKennt ihr andere Methoden? Teilt sie in den Kommentaren.<br \/>\n<br \/>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/tensor\/blog\/489900\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0420\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0447\u0442\u043e-\u0442\u043e \u043c\u0430\u0441\u0441\u043e\u0432\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0438\u0441\u044f\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u044b. \u042f \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0435, \u0430 \u043a\u0430\u043a \u2014 \u043b\u0443\u0447\u0448\u0435 \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0432\u0442\u043e\u0440\u043e\u043c \u0430\u0441\u043f\u0435\u043a\u0442\u0435 \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u2014 \u043e \u0441\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u043c \u043d\u0430\u0434\u043e \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u0432\u0438\u0441\u0438\u0442 \u0437\u043b\u043e\u0431\u043d\u044b\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440 ON UPDATE, \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044f\u0449\u0438\u0439 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-72265","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0420\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0447\u0442\u043e-\u0442\u043e \u043c\u0430\u0441\u0441\u043e\u0432\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0438\u0441\u044f\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u044b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/postgresql-antipatterns-menyaem-dannye-v-obhod-triggera\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47PostgreSQL Antipatterns: \u043c\u0435\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0431\u0445\u043e\u0434 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0420\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0447\u0442\u043e-\u0442\u043e \u043c\u0430\u0441\u0441\u043e\u0432\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0438\u0441\u044f\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u044b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/postgresql-antipatterns-menyaem-dannye-v-obhod-triggera\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-03-03T05:42:17+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:13:51+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47PostgreSQL Antipatterns: Daten\u00e4nderung um den Trigger herum | ProHoster","description":"Fr\u00fcher oder sp\u00e4ter stehen viele vor der Notwendigkeit, etwas massenhaft in den Datens\u00e4tzen einer Tabelle zu korrigieren.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/postgresql-antipatterns-menyaem-dannye-v-obhod-triggera","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47PostgreSQL Antipatterns: \u043c\u0435\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043e\u0431\u0445\u043e\u0434 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 | ProHoster","og:description":"\u0420\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0447\u0442\u043e-\u0442\u043e \u043c\u0430\u0441\u0441\u043e\u0432\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0438\u0441\u044f\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u044b.","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/postgresql-antipatterns-menyaem-dannye-v-obhod-triggera","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-03-03T05:42:17+00:00","article:modified_time":"2020-03-03T13:13:51+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"72265","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 18:47:24","updated":"2022-09-27 18:26:38","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/72265","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=72265"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/72265\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=72265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=72265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=72265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}