Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wOugK-000HOm-0r for pgpool-hackers@arkaria.postgresql.org; Mon, 18 May 2026 09:54:40 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wOugH-001bzB-0I for pgpool-hackers@arkaria.postgresql.org; Mon, 18 May 2026 09:54:38 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wOugG-001bz3-2X for pgpool-hackers@lists.postgresql.org; Mon, 18 May 2026 09:54:37 +0000 Received: from mail-yx1-xb131.google.com ([2607:f8b0:4864:20::b131]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wOugE-00000000ANN-1VBz for pgpool-hackers@lists.postgresql.org; Mon, 18 May 2026 09:54:36 +0000 Received: by mail-yx1-xb131.google.com with SMTP id 956f58d0204a3-65c364b893aso2293798d50.0 for ; Mon, 18 May 2026 02:54:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779098072; cv=none; d=google.com; s=arc-20240605; b=am/W+J1z0g/RsqWMPb2s/34vnjnxj1ZKkp1QQicv04dNg00q5D/xtezv3jEhTYw9Dd Shl32/xaKIuRtFJVUWF+pRpyA+bBfhJv5dTdwXEV71noclg4ofT3V23qbt/6MPPrka03 ZadRPmnrr/pwGBYCyEdxGVr8UJhXrBnNYvbgeuqQBdEz+z9UtZ3Ual1F34T+vAYnfAt3 gWnqvf6zlMrC6ZkSIB0y/SFt2JhmSbqm99lMZihtp2ooi/FaGmlw8W9OBfQ4AWKlu0/m Pr6rUX/J9IIR+UYrd/5SZ7wdEPa5dvSyJ94puLiBLZz0QulPZ7f3l9BNxd5OP3kEF/DZ qpxw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=9l3MQWP5kxdRF6hL4k0Q6WsIIS8tcUA+qBid/BNxMiQ=; fh=m3oiE62fRN5J1XaE+5vpHZRIgCyFefxVI0mFw3d8yxA=; b=EMRxEQBCcW4VTwnAvza5VfUSFTUkjcBCpu8Vp5POakJYFUcIX6LmG6E2nJTZuOP76p ZRewIRPJZxy+P6fVj0uX6AKisjej8yRlbcQOqp/AXkKbQdxQohb5TITsPlJjDinMTM0p jIbPWbDF8OyAqCwCQoZ0PeX5qp7hnXg19SGGn7/FT2MZ7ni4aQ1C0w/isuytwq7OZpph 733DKkXbtvw1m3xx7ZxSmFlb3KDVOjX0Vgx63vcvhUK6SNxQk73MckWI2gREAFdWoxsf ejN7H6vCoaEBwzi+DbeBKrc9veNjAkXwwBQYTj0FPa5mkBgeBXrRuhi3KO1vbj775zcs mCuQ==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tailorbrands.com; s=google; t=1779098072; x=1779702872; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=9l3MQWP5kxdRF6hL4k0Q6WsIIS8tcUA+qBid/BNxMiQ=; b=ByfKzT+2nQXOaw72zOU04vHqX/8WHFSku48GcIipYfp8hT1qkSJvcL1wQTBXfQZ/fN JOXm4MhBgwZIiFyPsky0YrWp1vkiyTqSYc5WclYitq+yZ9mLTCUppO19DxzaLSOj/mpF m43x9zcP1nA/ZPA5dxAd6ubVll8ZABaeN0XI5gIYvzcgeNVHdShWMpAHxbQFd//i0kCg eFOybvdZUOQaD56qFR2tEt2Iq69yOCO7tY/b7JLy366/qfr1UJwOgUprdhIevvhRXn1T 6qCamNeueMUs3WIeuLAd0U8AzvoS1vFxAWBNVznsjSTnzGn5ODQid3QvO7VF2fhaQ0AG F7/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779098072; x=1779702872; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=9l3MQWP5kxdRF6hL4k0Q6WsIIS8tcUA+qBid/BNxMiQ=; b=AtjdPv5OSIKB5vCGfbwbb54TQonWMBxOvCDyhZMvgpOOX9W7hZ9kIGYMgGc9N+VNk+ FPwLcTQfc8LVtgovQ/1rb1cl/fknyEmkmFuykTDhEf46jhGwC/CWtX7hT5twN60/pi0q JsPMH0Aa2nXngQ2/fAN6BcVuSDTmClMk0+ClDRdfRV8A9upLMi794kPRYxKIN3atoTs+ VZoUPDGiiOSzK4HVYyXKLaPgTIXfWxDu5Y3Q0Ee1vPLimSGeW2+D2+caVSASly6JY6gM 29qGA8nGjpmFG3A+5YPihpKhZ8vE5JGrWrQVqqoQJpPqxiz69woWApQrVu7cxEg98akC rSpQ== X-Gm-Message-State: AOJu0YzXoZgZF8j3K0/oomv8drrsgw1vHIv1BFmFTupXnSIh4OeO+X2j rvhL4Q7qHUzIUskIijrgRvi66SUUSLKhuChggw2Oe2jIyxiDAXpiRrDptzMgSt/dT9F7Xvw5Thv C8zGnGV7D+XPi2w88MVJ+WP+1KixdAlvgeeFWZ11mlLUNg40FIlZjJ/6Rqg== X-Gm-Gg: Acq92OE1yykV5Wou16v++0Xn55sJaTDBfkbntHxSZ35UysX2+oYToEuIP59ETWiFDvF aNRMvqInZtRSjfAnjiFQcZGDdNvLq45c1qpZhKawMl3BaMptoWbtlcsJfYYnx1iTwarfSx/Ge7G 2kRH/cU1itrVh3jLKSeanabtpXE7X0TtpuVvb57wz/oq3xYyNy/hOjgyq1FOfnjHozsyLId/NjM V4sEcHSRHFCJj1gPr8YhfFklKqCb41WCi1UEYorSpqbVzP5j+bk9lxZSHA9i4Hhv78q4MtvzkDX 5aYtCEenDCGNyPaa11mIxOFv+//fvoYxeMlpdUuJmzI8YiqjdDnTaZIj1GJ6Al748GUxMgx6Xqr /b3sQorBaAC/eVM2pswCg5ryr0GxBkSmcxdEa X-Received: by 2002:a05:690c:62c6:b0:7b6:de92:adb5 with SMTP id 00721157ae682-7c95caf23e0mr160286327b3.49.1779098072010; Mon, 18 May 2026 02:54:32 -0700 (PDT) MIME-Version: 1.0 References: <20260419.162444.1985634870518309110.ishii@postgresql.org> <20260423.171408.1934918588656421138.ishii@postgresql.org> In-Reply-To: From: Nadav Shatz Date: Mon, 18 May 2026 12:54:20 +0300 X-Gm-Features: AVHnY4KAzR0Sqbukl7Hj5zjH7Xx3fCu3zV2x1Gzb9IVKMBhhG8GOQWmutQ0VfXw Message-ID: Subject: Re: Proposal: Recent mutated table tracking in memory To: Tatsuo Ishii Cc: pgpool-hackers@lists.postgresql.org Content-Type: multipart/alternative; boundary="0000000000009a7a170652148c17" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000009a7a170652148c17 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Tatsuo, Any update on this proposal? Thanks On Thu, Apr 23, 2026 at 5:16=E2=80=AFPM Nadav Shatz wrote: > Hi Tatsuo, > > Good catch on the 006.memqcache timeout. My previous fix had > wrong side effects -- setting writing_transaction for > dml_adaptive_global also changed routing behavior (it forced the > whole transaction to primary, effectively reducing the feature to > 'transaction' mode). That's what caused the hang. > > Fixed properly in v3: instead of touching writing_transaction, > added a memqcache-specific guard that checks whether the current > dml_adaptive* session has tracked writes in the current > transaction, and skips the cache fetch if so. > > Attached: v3-0001-Feature-load-balancing-control-by-table-tracking.patch > > Changes in v3 vs v2: > > - pool_set_writing_transaction() reverted to original behavior > (dml_adaptive_global no longer sets writing_transaction, so > routing stays per-table as intended). > > - Added new helper pool_has_dml_adaptive_write_in_transaction() > in pool_session_context.c. Returns true when the current session > is in dml_adaptive* mode, is inside an explicit transaction, and > has already tracked at least one write (via > transaction_temp_write_list). > > - The two memqcache fetch guards in pool_proto_modules.c > (simple query at line 270, extended query at line 1028) now > also call !pool_has_dml_adaptive_write_in_transaction(). > Autocommit writes in dml_adaptive_global are still handled by > the existing pool_invalidate_query_cache() at COMMIT time -- > no change needed there. > > Verified locally by mutating 006.memqcache with > disable_load_balance_on_write =3D 'dml_adaptive_global' in the > streaming replication mode (the only mode where dml_adaptive > applies) and the jdbctest now correctly returns "2" instead of > the stale cached "1". Both 006.memqcache and 043.track_table_mutation > pass. > > Thanks! > > On Thu, Apr 23, 2026 at 11:14=E2=80=AFAM Tatsuo Ishii > wrote: > >> Hi Nadav, >> >> Unfortunately the mutated 006.memqcache failed (timeout). >> >> >> > memqcache bug fix >> >> > ----------------- >> >> > >> >> > Good catch. The root cause: pool_set_writing_transaction() was >> >> > explicitly skipping dml_adaptive_global, so >> >> > pool_is_writing_transaction() always returned false in this mode. >> >> > The query cache fetch guard at pool_proto_modules.c:270 >> >> > (!pool_is_writing_transaction()) then served stale cached results >> >> > after DML in the same transaction. >> >> > >> >> > Fix: pool_set_writing_transaction() now sets the flag for >> >> > dml_adaptive_global (only 'off' and 'dml_adaptive' skip it). This >> >> > ensures the query cache is properly bypassed after writes within >> >> > the same transaction. >> >> Regards, >> -- >> Tatsuo Ishii >> SRA OSS K.K. >> English: http://www.sraoss.co.jp/index_en/ >> Japanese:http://www.sraoss.co.jp >> >> > Hi Tatsuo, >> > >> > Rebased onto current master, renumbered the regression tests >> > (043/044 to avoid collision with the new 042.ssl_reload), and >> > combined everything into a single commit. >> > >> > Attached: v2-0001-Feature-load-balancing-control-by-table-tracking.pat= ch >> > >> > Looking forward to your review. >> > >> > >> > On Sun, Apr 19, 2026 at 10:25=E2=80=AFAM Tatsuo Ishii >> wrote: >> > >> >> > Hi Tatsuo, >> >> > >> >> > hank you for the detailed review. Attached patch addresses all item= s. >> >> >> >> I guess the attached patch is on top of >> >> v1-0001-Feature-load-balancing-control-by-table-tracking.patch. To >> >> apply v2-0001-address-review.patch, we need to apply >> >> v1-0001-Feature-load-balancing-control-by-table-tracking.patch first. >> >> Unfortunately due to recent commit, it does not apply anymore. Can yo= u >> >> please provide v1 + v2 that are rebased against latest master branch? >> >> Also 042 regression test is already used by recent commit. Can you >> >> renumber 042.track_table_mutation and >> >> 043.track_table_mutation_watchdog to 043.track_table_mutation and >> >> 044.track_table_mutation_watchdog accordingly? >> >> >> >> Looking forward to seeing new patch. >> >> >> >> Regards, >> >> -- >> >> Tatsuo Ishii >> >> SRA OSS K.K. >> >> English: http://www.sraoss.co.jp/index_en/ >> >> Japanese:http://www.sraoss.co.jp >> >> >> >> >> >> > memqcache bug fix >> >> > ----------------- >> >> > >> >> > Good catch. The root cause: pool_set_writing_transaction() was >> >> > explicitly skipping dml_adaptive_global, so >> >> > pool_is_writing_transaction() always returned false in this mode. >> >> > The query cache fetch guard at pool_proto_modules.c:270 >> >> > (!pool_is_writing_transaction()) then served stale cached results >> >> > after DML in the same transaction. >> >> > >> >> > Fix: pool_set_writing_transaction() now sets the flag for >> >> > dml_adaptive_global (only 'off' and 'dml_adaptive' skip it). This >> >> > ensures the query cache is properly bypassed after writes within >> >> > the same transaction. >> >> > >> >> > Removed dead query parse cache code (~700 lines) >> >> > ------------------------------------------------- >> >> > >> >> > You're right -- pool_track_table_mutation_get_cached_parse, >> >> > pool_track_table_mutation_cache_parse, and >> >> > pool_track_table_mutation_normalize_and_hash were never called. >> >> > These were leftover from an earlier design where we planned to >> >> > cache SQL parse results in shared memory. The feature ended up >> >> > using pgpool's existing parser directly, and this code was never >> >> > wired up. >> >> > >> >> > Removed: QueryParseCache and QueryParseEntry structs, all related >> >> > static functions, the TRACK_TABLE_MUTATION_QUERY_SEM semaphore, >> >> > and the track_table_mutation_query_buckets / >> >> > track_table_mutation_query_parse_cache_size configuration >> >> > parameters. This also reduces shared memory usage from ~6.4 MB >> >> > to ~80 KB with default settings. >> >> > >> >> > check_object_relationship_list scope >> >> > ------------------------------------- >> >> > >> >> > You're correct -- dml_adaptive_global does not use >> >> > dml_adaptive_object_relationship_list. Changed >> >> > check_object_relationship_list() to check for DLBOW_DML_ADAPTIVE >> >> > only, not DLBOW_IS_DML_ADAPTIVE (which includes global). >> >> > >> >> > Documentation fixes >> >> > ------------------- >> >> > >> >> > - Removed "(Lagless Replica Reads)" from section title and >> >> > "lagless" language from description. >> >> > >> >> > - Described fallback behavior when neither >> >> > replication_delay_source_cmd nor delay_threshold_by_time is >> >> > configured (TTL stays at 100ms default minimum). >> >> > >> >> > - "query cache" references removed (the query parse cache is gone). >> >> > >> >> > - Added 128-table-per-SELECT limit to Limitations section >> >> > (uses POOL_MAX_SELECT_OIDS). >> >> > >> >> > Code style fixes >> >> > ---------------- >> >> > >> >> > - DLBOW_IS_DML_ADAPTIVE() calls no longer split across lines. >> >> > >> >> > - Split the long errmsg line in >> >> > is_select_object_in_temp_write_list. >> >> > >> >> > - Removed redundant is_adaptive variable in >> >> > is_select_object_in_temp_write_list (the check at function >> >> > entry already guarantees it). >> >> > >> >> > Thanks! >> >> > >> >> > On Wed, Apr 15, 2026 at 1:43=E2=80=AFAM Tatsuo Ishii >> >> wrote: >> >> > >> >> >> Hi Nadav, >> >> >> >> >> >> > Hi Tatsuo, >> >> >> > >> >> >> > Looks good to me thanks! >> >> >> > >> >> >> > Please go ahead with your review. waiting to hear back from you. >> >> >> >> >> >> Here are the code review results. >> >> >> >> >> >> diff --git a/doc/src/sgml/loadbalance.sgml >> >> b/doc/src/sgml/loadbalance.sgml >> >> >> index 9e1e7b39b..7384ce81a 100644 >> >> >> --- a/doc/src/sgml/loadbalance.sgml >> >> >> +++ b/doc/src/sgml/loadbalance.sgml >> >> >> : >> >> >> + >> >> >> + Table Mutation Map Configuration (Lagless Replica >> >> Reads) >> >> >> >> >> >> "(Lagless Replica Reads)" sounds like an advertisement to me. It >> >> >> should be removed. >> >> >> >> >> >> + >> >> >> + These parameters configure the track table mutation feature, >> which >> >> is >> >> >> activated by setting >> >> >> + to >> >> >> dml_adaptive_global. >> >> >> + The feature tracks recently written tables to prevent stale >> reads >> >> from >> >> >> replica nodes during >> >> >> + replication lag, implementing the "lagless" architecture >> pattern for >> >> >> distributed systems >> >> >> + with read replicas. >> >> >> >> >> >> I think the feature does not guarantee "lagless" anytime, in all >> cases. >> >> >> >> >> >> + >> >> >> + This feature requires time-based replication delay monitoring. >> This >> >> >> can be provided by either >> >> >> + (external >> command >> >> >> mode) or by setting >> >> >> + (which uses >> >> >> pg_stat_replication.replay_lag >> >> >> + from PostgreSQL 10+). At least one of these must be configured >> for >> >> the >> >> >> TTL calculation to work. >> >> >> >> >> >> If one of these is not set, what happens? Error? Need to describe >> it. >> >> >> >> >> >> + >> >> >> + >> >> >> + >> >> >> + >> >> >> + Enabling dml_adaptive_global increases >> shared >> >> >> memory consumption. With default settings, >> >> >> + the feature requires approximately 6.4 MB of shared memory >> (0.1 MB >> >> >> for table tracking + 6.3 MB for query cache). >> >> >> >> >> >> "query cache" should be "query parse cache". >> >> >> >> >> >> + Memory usage scales with configuration parameters: >> >> >> + >> >> >> + >> >> >> + >> >> >> + >> >> >> + Table tracking: track_table_mutation_table_size * = 40 >> >> >> bytes (default: 2048 * 40 =3D ~80 KB) >> >> >> + >> >> >> + >> >> >> + >> >> >> + >> >> >> + Query cache: >> >> track_table_mutation_query_parse_cache_size * >> >> >> 640 bytes (default: 10000 * 640 =3D ~6.3 MB) >> >> >> >> >> >> "query cache" should be "query parse cache". >> >> >> >> >> >> + Limitations >> >> >> >> >> >> I think number of tables tacked in a SELECT is limited to 8. It >> should >> >> >> be mentioned. >> >> >> >> >> >> diff --git a/src/context/pool_query_context.c >> >> >> b/src/context/pool_query_context.c >> >> >> index a056ac596..0190d3673 100644 >> >> >> --- a/src/context/pool_query_context.c >> >> >> +++ b/src/context/pool_query_context.c >> >> >> @@ -1828,15 +1829,23 @@ is_in_list(char *name, List *list) >> >> >> static bool >> >> >> is_select_object_in_temp_write_list(Node *node, void *context) >> >> >> { >> >> >> - if (node =3D=3D NULL || >> pool_config->disable_load_balance_on_write >> >> !=3D >> >> >> DLBOW_DML_ADAPTIVE) >> >> >> + if (node =3D=3D NULL || >> >> >> + !DLBOW_IS_DML_ADAPTIVE( >> >> >> + >> >> >> pool_config->disable_load_balance_on_write)) >> >> >> >> >> >> You don't need to split the line. >> >> >> >> >> >> + is_adaptive =3D DLBOW_IS_DML_ADAPTIVE( >> >> >> + >> >> >> pool_config->disable_load_balance_on_write); >> >> >> >> >> >> You don't need to split the line. >> >> >> >> >> >> - if (pool_config->disable_load_balance_on_write =3D= =3D >> >> >> DLBOW_DML_ADAPTIVE && session_context->is_in_transaction) >> >> >> + if (is_adaptive && >> >> >> + session_context->is_in_transaction) >> >> >> { >> >> >> ereport(DEBUG1, >> >> >> >> >> >> (errmsg("is_select_object_in_temp_write_list: \"%s\", found relati= on >> >> >> \"%s\"", (char *) context, rgv->relname))); >> >> >> This line is too long. Please split. >> >> >> >> >> >> @@ -1880,7 +1889,13 @@ static char >> >> >> *get_associated_object_from_dml_adaptive_relations >> >> >> void >> >> >> check_object_relationship_list(char *name, bool is_func_name) >> >> >> { >> >> >> - if (pool_config->disable_load_balance_on_write =3D=3D >> >> >> DLBOW_DML_ADAPTIVE && >> >> >> pool_config->parsed_dml_adaptive_object_relationship_list) >> >> >> + bool is_adaptive; >> >> >> + >> >> >> + is_adaptive =3D DLBOW_IS_DML_ADAPTIVE( >> >> >> + >> >> >> pool_config->disable_load_balance_on_write); >> >> >> >> >> >> I wrote in the commit message: >> >> >> >> >> >> modifications are only detected in the same transaction). Note, >> >> >> however, you cannot use dml_adaptive_object_relationship_list to >> track >> >> >> dependency among table and other objects. >> >> >> >> >> >> In my understanding the feature does not use >> >> >> dml_adaptive_object_relationship_list. If this is correct, why >> >> >> check_object_relationship_list() is called here in case >> >> >> dml_adaptive_global? If the feature uses >> >> >> dml_adaptive_object_relationship_list, test cases should be >> included. >> >> >> >> >> >> diff --git a/src/utils/pool_track_table_mutation.c >> >> >> b/src/utils/pool_track_table_mutation.c >> >> >> new file mode 100644 >> >> >> index 000000000..9be46b28f >> >> >> --- /dev/null >> >> >> +++ b/src/utils/pool_track_table_mutation.c >> >> >> >> >> >> It seems following functions are not used anywhere. I wonder if th= is >> >> >> feature actually use "query parse cache". >> >> >> >> >> >> pool_track_table_mutation_get_cached_parse >> >> >> pool_track_table_mutation_cache_parse >> >> >> pool_track_table_mutation_normalize_and_hash >> >> >> >> >> >> Besides the code review, I mutated one of regression tests to chec= k >> >> >> whether the feature co exists with in the existing memory query >> cache >> >> >> feature. After attached patch applied, I ran 006.memqcache and got >> the >> >> >> following result. >> >> >> >> >> >> cd src/test/regression >> >> >> ./regress.sh 006 >> >> >> creating pgpool-II temporary installation ... >> >> >> moving pgpool_setup to temporary installation path ... >> >> >> moving watchdog_setup to temporary installation path ... >> >> >> using pgpool-II at >> >> >> >> >> >> /home/t-ishii/work/Pgpool-II/current/pgpool2/src/test/regression/temp/in= stalled >> >> >> ************************* >> >> >> REGRESSION MODE : install >> >> >> Pgpool-II version : pgpool-II version 4.8devel >> (mitsukakeboshi) >> >> >> Pgpool-II install path : >> >> >> >> >> >> /home/t-ishii/work/Pgpool-II/current/pgpool2/src/test/regression/temp/in= stalled >> >> >> PostgreSQL bin : /usr/local/pgsql/bin >> >> >> PostgreSQL Major version : 18 >> >> >> pgbench : /usr/local/pgsql/bin/pgbench >> >> >> PostgreSQL jdbc : >> >> >> /usr/local/pgsql/share/postgresql-9.2-1003.jdbc4.jar >> >> >> ************************* >> >> >> testing 006.memqcache...failed. >> >> >> out of 1 ok:0 failed:1 timeout:0 >> >> >> >> >> >> log/006.memqcache shows: >> >> >> >> >> >> ../expected.txt result.txt differ: char 1, line 1 >> >> >> >> >> >> So I checked the test script and found the error was generated by = a >> >> >> Java program test. >> >> >> >> >> >> java jdbctest > result.txt 2>&1 >> >> >> cmp ../expected.txt result.txt >> >> >> if [ $? !=3D 0 ];then >> >> >> ./shutdownall >> >> >> exit 1 >> >> >> fi >> >> >> >> >> >> In jdbctest.java: >> >> >> >> >> >> /* >> >> >> * Cache test in an explicit transaction >> >> >> */ >> >> >> conn.setAutoCommit(false); >> >> >> // execute DML. This should prevent SELECTs from >> using >> >> >> query cache in the transaction. >> >> >> sql =3D "UPDATE t1 SET i =3D 2;"; >> >> >> pst =3D conn.createStatement(); >> >> >> pst.executeUpdate(sql); >> >> >> pst.close(); >> >> >> // should not use the cache and should return "2", >> >> rather >> >> >> than "1" >> >> >> prest =3D conn.prepareStatement("SELECT * FROM t1"= ); >> >> >> rs =3D prest.executeQuery(); >> >> >> >> >> >> The expected file (expected.txt) has "2" but the result file >> >> >> (testdir/result.txt) was "1". This is the reason why the test >> >> >> failed. I wonder if there's something wrong with the feature when >> the >> >> >> query cache is enabled. Can you look into this? >> >> >> >> >> >> Regards, >> >> >> -- >> >> >> Tatsuo Ishii >> >> >> SRA OSS K.K. >> >> >> English: http://www.sraoss.co.jp/index_en/ >> >> >> Japanese:http://www.sraoss.co.jp >> >> >> >> >> > >> >> > >> >> > -- >> >> > Nadav Shatz >> >> > Tailor Brands | CTO >> >> >> > >> > >> > -- >> > Nadav Shatz >> > Tailor Brands | CTO >> > > > -- > Nadav Shatz > Tailor Brands | CTO > --=20 Nadav Shatz Tailor Brands | CTO --0000000000009a7a170652148c17 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Tatsuo,

Any update on this proposal?=

Thanks

On Thu, Apr 23,= 2026 at 5:16=E2=80=AFPM Nadav Shatz <nadav@tailorbrands.com> wrote:
Hi Tatsuo,

Good catch= on the 006.memqcache timeout. My previous fix had
wrong side effects --= setting writing_transaction for
dml_adaptive_global also changed routin= g behavior (it forced the
whole transaction to primary, effectively redu= cing the feature to
'transaction' mode). That's what caused = the hang.

Fixed properly in v3: instead of touching writing_transact= ion,
added a memqcache-specific guard that checks whether the currentdml_adaptive* session has tracked writes in the current
transaction, an= d skips the cache fetch if so.

Attached: v3-0001-Feature-load-balanc= ing-control-by-table-tracking.patch

Changes in v3 vs v2:

- po= ol_set_writing_transaction() reverted to original behavior
=C2=A0 (dml_a= daptive_global no longer sets writing_transaction, so
=C2=A0 routing sta= ys per-table as intended).

- Added new helper pool_has_dml_adaptive_= write_in_transaction()
=C2=A0 in pool_session_context.c. Returns true wh= en the current session
=C2=A0 is in dml_adaptive* mode, is inside an exp= licit transaction, and
=C2=A0 has already tracked at least one write (vi= a
=C2=A0 transaction_temp_write_list).

- The two memqcache fetch = guards in pool_proto_modules.c
=C2=A0 (simple query at line 270, extende= d query at line 1028) now
=C2=A0 also call !pool_has_dml_adaptive_write_= in_transaction().
=C2=A0 Autocommit writes in dml_adaptive_global are st= ill handled by
=C2=A0 the existing pool_invalidate_query_cache() at COMM= IT time --
=C2=A0 no change needed there.

Verified locally by mut= ating 006.memqcache with
disable_load_balance_on_write =3D 'dml_adap= tive_global' in the
streaming replication mode (the only mode where = dml_adaptive
applies) and the jdbctest now correctly returns "2&quo= t; instead of
the stale cached "1". Both 006.memqcache and 043= .track_table_mutation
pass.

Thanks!

On Thu, Apr 23, 2026 at 11:14= =E2=80=AFAM Tatsuo Ishii <ishii@postgresql.org> wrote:
Hi Nadav,

Unfortunately the mutated 006.memqcache failed (timeout).

>> > memqcache bug fix
>> > -----------------
>> >
>> > Good catch. The root cause: pool_set_writing_transaction() wa= s
>> > explicitly skipping dml_adaptive_global, so
>> > pool_is_writing_transaction() always returned false in this m= ode.
>> > The query cache fetch guard at pool_proto_modules.c:270
>> > (!pool_is_writing_transaction()) then served stale cached res= ults
>> > after DML in the same transaction.
>> >
>> > Fix: pool_set_writing_transaction() now sets the flag for
>> > dml_adaptive_global (only 'off' and 'dml_adaptive= ' skip it). This
>> > ensures the query cache is properly bypassed after writes wit= hin
>> > the same transaction.

Regards,
--
Tatsuo Ishii
SRA OSS K.K.
English: http://www.sraoss.co.jp/index_en/
Japanese:http://www.sraoss.co.jp

> Hi Tatsuo,
>
> Rebased onto current master, renumbered the regression tests
> (043/044 to avoid collision with the new 042.ssl_reload), and
> combined everything into a single commit.
>
> Attached: v2-0001-Feature-load-balancing-control-by-table-tracking.pat= ch
>
> Looking forward to your review.
>
>
> On Sun, Apr 19, 2026 at 10:25=E2=80=AFAM Tatsuo Ishii <ishii@postgresql.org> = wrote:
>
>> > Hi Tatsuo,
>> >
>> > hank you for the detailed review. Attached patch addresses al= l items.
>>
>> I guess the attached patch is on top of
>> v1-0001-Feature-load-balancing-control-by-table-tracking.patch.=C2= =A0 To
>> apply v2-0001-address-review.patch, we need to apply
>> v1-0001-Feature-load-balancing-control-by-table-tracking.patch fir= st.
>> Unfortunately due to recent commit, it does not apply anymore. Can= you
>> please provide v1 + v2 that are rebased against latest master bran= ch?
>> Also 042 regression test is already used by recent commit. Can you=
>> renumber 042.track_table_mutation and
>> 043.track_table_mutation_watchdog to 043.track_table_mutation and<= br> >> 044.track_table_mutation_watchdog accordingly?
>>
>> Looking forward to seeing new patch.
>>
>> Regards,
>> --
>> Tatsuo Ishii
>> SRA OSS K.K.
>> English: http://www.sraoss.co.jp/index_en/
>> Japanese:http://www.sraoss.co.jp
>>
>>
>> > memqcache bug fix
>> > -----------------
>> >
>> > Good catch. The root cause: pool_set_writing_transaction() wa= s
>> > explicitly skipping dml_adaptive_global, so
>> > pool_is_writing_transaction() always returned false in this m= ode.
>> > The query cache fetch guard at pool_proto_modules.c:270
>> > (!pool_is_writing_transaction()) then served stale cached res= ults
>> > after DML in the same transaction.
>> >
>> > Fix: pool_set_writing_transaction() now sets the flag for
>> > dml_adaptive_global (only 'off' and 'dml_adaptive= ' skip it). This
>> > ensures the query cache is properly bypassed after writes wit= hin
>> > the same transaction.
>> >
>> > Removed dead query parse cache code (~700 lines)
>> > -------------------------------------------------
>> >
>> > You're right -- pool_track_table_mutation_get_cached_pars= e,
>> > pool_track_table_mutation_cache_parse, and
>> > pool_track_table_mutation_normalize_and_hash were never calle= d.
>> > These were leftover from an earlier design where we planned t= o
>> > cache SQL parse results in shared memory. The feature ended u= p
>> > using pgpool's existing parser directly, and this code wa= s never
>> > wired up.
>> >
>> > Removed: QueryParseCache and QueryParseEntry structs, all rel= ated
>> > static functions, the TRACK_TABLE_MUTATION_QUERY_SEM semaphor= e,
>> > and the track_table_mutation_query_buckets /
>> > track_table_mutation_query_parse_cache_size configuration
>> > parameters. This also reduces shared memory usage from ~6.4 M= B
>> > to ~80 KB with default settings.
>> >
>> > check_object_relationship_list scope
>> > -------------------------------------
>> >
>> > You're correct -- dml_adaptive_global does not use
>> > dml_adaptive_object_relationship_list. Changed
>> > check_object_relationship_list() to check for DLBOW_DML_ADAPT= IVE
>> > only, not DLBOW_IS_DML_ADAPTIVE (which includes global).
>> >
>> > Documentation fixes
>> > -------------------
>> >
>> > - Removed "(Lagless Replica Reads)" from section ti= tle and
>> >=C2=A0 =C2=A0"lagless" language from description. >> >
>> > - Described fallback behavior when neither
>> >=C2=A0 =C2=A0replication_delay_source_cmd nor delay_threshold_= by_time is
>> >=C2=A0 =C2=A0configured (TTL stays at 100ms default minimum).<= br> >> >
>> > - "query cache" references removed (the query parse= cache is gone).
>> >
>> > - Added 128-table-per-SELECT limit to Limitations section
>> >=C2=A0 =C2=A0(uses POOL_MAX_SELECT_OIDS).
>> >
>> > Code style fixes
>> > ----------------
>> >
>> > - DLBOW_IS_DML_ADAPTIVE() calls no longer split across lines.=
>> >
>> > - Split the long errmsg line in
>> >=C2=A0 =C2=A0is_select_object_in_temp_write_list.
>> >
>> > - Removed redundant is_adaptive variable in
>> >=C2=A0 =C2=A0is_select_object_in_temp_write_list (the check at= function
>> >=C2=A0 =C2=A0entry already guarantees it).
>> >
>> > Thanks!
>> >
>> > On Wed, Apr 15, 2026 at 1:43=E2=80=AFAM Tatsuo Ishii <ishii@postgresql.org<= /a>>
>> wrote:
>> >
>> >> Hi Nadav,
>> >>
>> >> > Hi Tatsuo,
>> >> >
>> >> > Looks good to me thanks!
>> >> >
>> >> > Please go ahead with your review. waiting to hear ba= ck from you.
>> >>
>> >> Here are the code review results.
>> >>
>> >> diff --git a/doc/src/sgml/loadbalance.sgml
>> b/doc/src/sgml/loadbalance.sgml
>> >> index 9e1e7b39b..7384ce81a 100644
>> >> --- a/doc/src/sgml/loadbalance.sgml
>> >> +++ b/doc/src/sgml/loadbalance.sgml
>> >> :
>> >> + <sect2 id=3D"runtime-config-table-mutation-map&= quot;>
>> >> +=C2=A0 <title>Table Mutation Map Configuration (La= gless Replica
>> Reads)</title>
>> >>
>> >> "(Lagless Replica Reads)" sounds like an advert= isement to me. It
>> >> should be removed.
>> >>
>> >> +=C2=A0 <para>
>> >> +=C2=A0 =C2=A0These parameters configure the track table = mutation feature, which
>> is
>> >> activated by setting
>> >> +=C2=A0 =C2=A0<xref linkend=3D"guc-disable-load-b= alance-on-write"> to
>> >> <literal>dml_adaptive_global</literal>.
>> >> +=C2=A0 =C2=A0The feature tracks recently written tables = to prevent stale reads
>> from
>> >> replica nodes during
>> >> +=C2=A0 =C2=A0replication lag, implementing the "lag= less" architecture pattern for
>> >> distributed systems
>> >> +=C2=A0 =C2=A0with read replicas.
>> >>
>> >> I think the feature does not guarantee "lagless"= ; anytime, in all cases.
>> >>
>> >> +=C2=A0 <para>
>> >> +=C2=A0 =C2=A0This feature requires time-based replicatio= n delay monitoring. This
>> >> can be provided by either
>> >> +=C2=A0 =C2=A0<xref linkend=3D"guc-replication-de= lay-source-cmd"> (external command
>> >> mode) or by setting
>> >> +=C2=A0 =C2=A0<xref linkend=3D"guc-delay-threshol= d-by-time"> (which uses
>> >> <literal>pg_stat_replication.replay_lag</literal= >
>> >> +=C2=A0 =C2=A0from PostgreSQL 10+). At least one of these= must be configured for
>> the
>> >> TTL calculation to work.
>> >>
>> >> If one of these is not set, what happens? Error? Need to = describe it.
>> >>
>> >> +=C2=A0 </para>
>> >> +
>> >> +=C2=A0 <warning>
>> >> +=C2=A0 =C2=A0<para>
>> >> +=C2=A0 =C2=A0 Enabling <literal>dml_adaptive_globa= l</literal> increases shared
>> >> memory consumption. With default settings,
>> >> +=C2=A0 =C2=A0 the feature requires approximately 6.4 MB = of shared memory (0.1 MB
>> >> for table tracking + 6.3 MB for query cache).
>> >>
>> >> "query cache" should be "query parse cache= ".
>> >>
>> >> +=C2=A0 =C2=A0 Memory usage scales with configuration par= ameters:
>> >> +=C2=A0 =C2=A0</para>
>> >> +=C2=A0 =C2=A0<itemizedlist>
>> >> +=C2=A0 =C2=A0 <listitem>
>> >> +=C2=A0 =C2=A0 =C2=A0<para>
>> >> +=C2=A0 =C2=A0 =C2=A0 Table tracking: <literal>trac= k_table_mutation_table_size * 40
>> >> bytes</literal> (default: 2048 * 40 =3D ~80 KB)
>> >> +=C2=A0 =C2=A0 =C2=A0</para>
>> >> +=C2=A0 =C2=A0 </listitem>
>> >> +=C2=A0 =C2=A0 <listitem>
>> >> +=C2=A0 =C2=A0 =C2=A0<para>
>> >> +=C2=A0 =C2=A0 =C2=A0 Query cache:
>> <literal>track_table_mutation_query_parse_cache_size *
>> >> 640 bytes</literal> (default: 10000 * 640 =3D ~6.3 = MB)
>> >>
>> >> "query cache" should be "query parse cache= ".
>> >>
>> >> +=C2=A0 =C2=A0<title>Limitations</title>
>> >>
>> >> I think number of tables tacked in a SELECT is limited to= 8. It should
>> >> be mentioned.
>> >>
>> >> diff --git a/src/context/pool_query_context.c
>> >> b/src/context/pool_query_context.c
>> >> index a056ac596..0190d3673 100644
>> >> --- a/src/context/pool_query_context.c
>> >> +++ b/src/context/pool_query_context.c
>> >> @@ -1828,15 +1829,23 @@ is_in_list(char *name, List *list= )
>> >>=C2=A0 static bool
>> >>=C2=A0 is_select_object_in_temp_write_list(Node *node, voi= d *context)
>> >>=C2=A0 {
>> >> -=C2=A0 =C2=A0 =C2=A0 =C2=A0if (node =3D=3D NULL || pool_= config->disable_load_balance_on_write
>> !=3D
>> >> DLBOW_DML_ADAPTIVE)
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0if (node =3D=3D NULL ||
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0!= DLBOW_IS_DML_ADAPTIVE(
>> >> +
>> >> pool_config->disable_load_balance_on_write))
>> >>
>> >> You don't need to split the line.
>> >>
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0i= s_adaptive =3D DLBOW_IS_DML_ADAPTIVE(
>> >> +
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pool_conf= ig->disable_load_balance_on_write);
>> >>
>> >> You don't need to split the line.
>> >>
>> >> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0i= f (pool_config->disable_load_balance_on_write =3D=3D
>> >> DLBOW_DML_ADAPTIVE && session_context->is_in_t= ransaction)
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0i= f (is_adaptive &&
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0session_context->is_in_transaction)
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0{
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ereport(DEBUG1,
>> >>
>> >> (errmsg("is_select_object_in_temp_write_list: \"= ;%s\", found relation
>> >> \"%s\"", (char *) context, rgv->relname= )));
>> >> This line is too long. Please split.
>> >>
>> >> @@ -1880,7 +1889,13 @@ static char
>> >> *get_associated_object_from_dml_adaptive_relations
>> >>=C2=A0 void
>> >>=C2=A0 check_object_relationship_list(char *name, bool is_= func_name)
>> >>=C2=A0 {
>> >> -=C2=A0 =C2=A0 =C2=A0 =C2=A0if (pool_config->disable_l= oad_balance_on_write =3D=3D
>> >> DLBOW_DML_ADAPTIVE &&
>> >> pool_config->parsed_dml_adaptive_object_relationship_l= ist)
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0bool=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 is_adaptive;
>> >> +
>> >> +=C2=A0 =C2=A0 =C2=A0 =C2=A0is_adaptive =3D DLBOW_IS_DML_= ADAPTIVE(
>> >> +
>> >>=C2=A0 =C2=A0 =C2=A0 pool_config->disable_load_balance_= on_write);
>> >>
>> >> I wrote in the commit message:
>> >>
>> >> modifications are only detected in the same transaction).= Note,
>> >> however, you cannot use dml_adaptive_object_relationship_= list to track
>> >> dependency among table and other objects.
>> >>
>> >> In my understanding the feature does not use
>> >> dml_adaptive_object_relationship_list. If this is correct= , why
>> >> check_object_relationship_list() is called here in case >> >> dml_adaptive_global?=C2=A0 If the feature uses
>> >> dml_adaptive_object_relationship_list, test cases should = be included.
>> >>
>> >> diff --git a/src/utils/pool_track_table_mutation.c
>> >> b/src/utils/pool_track_table_mutation.c
>> >> new file mode 100644
>> >> index 000000000..9be46b28f
>> >> --- /dev/null
>> >> +++ b/src/utils/pool_track_table_mutation.c
>> >>
>> >> It seems following functions are not used anywhere. I won= der if this
>> >> feature actually use "query parse cache".
>> >>
>> >> pool_track_table_mutation_get_cached_parse
>> >> pool_track_table_mutation_cache_parse
>> >> pool_track_table_mutation_normalize_and_hash
>> >>
>> >> Besides the code review, I mutated one of regression test= s to check
>> >> whether the feature co exists with in the existing memory= query cache
>> >> feature. After attached patch applied, I ran 006.memqcach= e and got the
>> >> following result.
>> >>
>> >> cd src/test/regression
>> >> ./regress.sh 006
>> >> creating pgpool-II temporary installation ...
>> >> moving pgpool_setup to temporary installation path ... >> >> moving watchdog_setup to temporary installation path ...<= br> >> >> using pgpool-II at
>> >>
>> /home/t-ishii/work/Pgpool-II/current/pgpool2/src/test/regression/t= emp/installed
>> >> *************************
>> >> REGRESSION MODE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 : insta= ll
>> >> Pgpool-II version=C2=A0 =C2=A0 =C2=A0 =C2=A0 : pgpool-II = version 4.8devel (mitsukakeboshi)
>> >> Pgpool-II install path=C2=A0 =C2=A0:
>> >>
>> /home/t-ishii/work/Pgpool-II/current/pgpool2/src/test/regression/t= emp/installed
>> >> PostgreSQL bin=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0: = /usr/local/pgsql/bin
>> >> PostgreSQL Major version : 18
>> >> pgbench=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 : /usr/local/pgsql/bin/pgbench
>> >> PostgreSQL jdbc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 :
>> >> /usr/local/pgsql/share/postgresql-9.2-1003.jdbc4.jar
>> >> *************************
>> >> testing 006.memqcache...failed.
>> >> out of 1 ok:0 failed:1 timeout:0
>> >>
>> >> log/006.memqcache shows:
>> >>
>> >> ../expected.txt result.txt differ: char 1, line 1
>> >>
>> >> So I checked the test script and found the error was gene= rated by a
>> >> Java program test.
>> >>
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0java jdbctest > resul= t.txt 2>&1
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cmp ../expected.txt resu= lt.txt
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if [ $? !=3D 0 ];then >> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0./shutdownall
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0exit 1
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fi
>> >>
>> >> In jdbctest.java:
>> >>
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0/*
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 * Cache test in an explicit transaction
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 */
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0conn.setAutoCommit(false);
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0// execute DML. This should prevent SELECTs from using
>> >> query cache in the transaction.
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0sql =3D "UPDATE t1 SET i =3D 2;";
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0pst =3D conn.createStatement();
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0pst.executeUpdate(sql);
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0pst.close();
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0// should not use the cache and should return "2",
>> rather
>> >> than "1"
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0prest =3D conn.prepareStatement("SELECT * FROM t1");
>> >>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0rs =3D prest.executeQuery();
>> >>
>> >> The expected file (expected.txt) has "2" but th= e result file
>> >> (testdir/result.txt) was "1".=C2=A0 This is the= reason why the test
>> >> failed. I wonder if there's something wrong with the = feature when the
>> >> query cache is enabled. Can you look into this?
>> >>
>> >> Regards,
>> >> --
>> >> Tatsuo Ishii
>> >> SRA OSS K.K.
>> >> English:
http://www.sraoss.co.jp/index_en/ >> >> Japanese:http://www.sraoss.co.jp
>> >>
>> >
>> >
>> > --
>> > Nadav Shatz
>> > Tailor Brands | CTO
>>
>
>
> --
> Nadav Shatz
> Tailor Brands | CTO


--
Nadav Shatz
<= font color=3D"#000000">Tailor Brands=C2=A0| CTO


--
Nadav Shatz
<= font color=3D"#000000">Tailor Brands=C2=A0| CTO
--0000000000009a7a170652148c17--