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.94.2) (envelope-from ) id 1qMaRR-002lOg-6o for psycopg@arkaria.postgresql.org; Thu, 20 Jul 2023 20:40:05 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1qMaRP-00HC8z-LN for psycopg@arkaria.postgresql.org; Thu, 20 Jul 2023 20:40:03 +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.94.2) (envelope-from ) id 1qMaRP-00HC7Z-E7 for psycopg@lists.postgresql.org; Thu, 20 Jul 2023 20:40:03 +0000 Received: from mail-oo1-xc2a.google.com ([2607:f8b0:4864:20::c2a]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1qMaRL-000nuU-EC for psycopg@postgresql.org; Thu, 20 Jul 2023 20:40:02 +0000 Received: by mail-oo1-xc2a.google.com with SMTP id 006d021491bc7-56368c40e8eso874599eaf.0 for ; Thu, 20 Jul 2023 13:39:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1689885598; x=1690490398; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=MGpBaIYGriYg8JGeNWWOTepKK8TprGcT8Rq4cQXFS2Q=; b=cAzC8uMk/OitSh9ICQnPnIJ/qs7/50tRjg3RZPDmAC2etDSs130fqvqkWosVfkL3KB bug8Mrwq31GK/HdMQW/fPutWXfNiUR35l2bFzxBd3eiKum2HKh9DW94+BDa8P/2fYin9 kD74r20tTdZ6+lZGRgKNpqfW1M8/NO+fRIWdSHzS3KJdJyG3R0R3RNMrTbAXUOlP0CrS 6EV9A88ZP0NoNrEJ0WNqc2zzCUm5yn/2t/lIc2wESFjGPT2x87O2fDumzeRNcF3221FP d+kunKk+XKLgxvnmqsswogUdDH40TZpZdgesHiiYAGqcCT5m+IN0w3/2dI37AUjWTd1+ 8Law== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689885598; x=1690490398; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=MGpBaIYGriYg8JGeNWWOTepKK8TprGcT8Rq4cQXFS2Q=; b=ZtTIHyKVHNXzRZ4p7hIM9kOdRZ2wQ3Rl3USSHPd1/5BhoXh6vGOLehXz4M6ll5LVUy Ds8UXjSnPhOWDzxsOxV0ES333W+tEqDYSX7DwjPWXbw4KaAGAf8Om27RywegriksmdLU 0MQZyBGxdGhH/rSR2eIvlC9KQ+zoXjZPvPZAKLQynVeJ9EruygL/6WJuT8q4b7Mmc+OD oYg9drt8T/IeTKDVRpLR5ZM+QzRPvkhd7W8ISyKqmvEs+K61isHS3DY0s9uOIRDZqa2q N4bLrJZAwOaLfiNW8wOSblS3cuqO/pbGsDXozN8bPnHktc+rBuqsBKPw7WUTMKMys1aa fo6A== X-Gm-Message-State: ABy/qLaYYOzjRWvbyLpF0yagSKGtMyHhqfveypVCXXWBvtUoPRy4dkfQ ff7bWLuvW28VtakJBgA9k4jsuhXb/nXkbx2XRwcqfDrMz8+4r4W4 X-Google-Smtp-Source: APBJJlEKI8NdLXlIgzWZwSnakgVXdsnXOKEVHWKCMYeJRxqXvTYzHGLNVqE4zanwrC/mPI8F37VqT4q7nQuZx/FrexA= X-Received: by 2002:a4a:4944:0:b0:566:f7c7:93bb with SMTP id z65-20020a4a4944000000b00566f7c793bbmr2976313ooa.4.1689885598349; Thu, 20 Jul 2023 13:39:58 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Daniele Varrazzo Date: Thu, 20 Jul 2023 21:39:46 +0100 Message-ID: Subject: Re: conn.read_only not honored in autocommit mode To: David Raymond Cc: Psycopg Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hello! On Tue, 18 Jul 2023 at 21:24, David Raymond wrote: > > It appears that the .read_only attribute of a connection is not honored when the connection is in autocommit mode. > > There's no mention of this on the Connection classes page for read_only, and in the section linked to in Transactions management you have to read it 3 times to realize it's only used with Connection.transaction(). Indeed. The docs at say: [transaction parameters] affect the transactions started implicitly by non-autocommit transactions and the ones started explicitly by Connection.transaction() for both autocommit and non-autocommit transactions. So yes, it's not explicit that *they don't affect implicit autocommit transactions*... because there is no transaction to affect. We can improve the docs by making it more explicit. > Is it the intent to not be used for regular autocommit connections, or is it an oversight? > > I used conn.set_session(readonly = True, deferrable = False, autocommit = True) in psycopg2, and that seemed to work at preventing accidental changes. > I've just been moving to psycopg recently, and with no set_session I replaced it with putting autocommit = True in the connection call and following it with .read_only = True and .deferrable = False This is indeed a difference of behaviour wrt psycopg2 and it should be documented in . The change comes from the fact that emulating parameters such as `read_only` in autocommit means using a radically different approach compared to non-autocommit mode: in non-autocommit mode there is syntax such as BEGIN READ ONLY that can be used, whereas in autocommit we call SET default_transaction_read_only in the session. This means that the session now has relevant state, connection pooling software may get in the way, and what happens if the user starts switching between autocommit and non-autocommit? Should we send SET default_transaction_read_only TO DEFAULT? I honestly don't remember what psycopg2 does. The problems with the use of SET default_transaction_XXX are documented in (see "changed in version 2.7"). For psycopg 3 we decided to avoid the problems/inconsistencies by limiting transaction attributes to... transactions, so only to the implicit (non-autocommit) and explicit (transaction() block) ones. > Since I vastly prefer autocommit mode, is my best bet then to replace > conn.read_only = True > with either > conn.execute("set session characteristics as transaction read only, not deferrable;") > or > conn.execute("set default_transaction_read_only to true;") > conn.execute("set default_transaction_deferrable to false;") > ? > > (Honestly in my mind I thought this is what changing .read_only, .deferrable, or .isolation_level did in the background already) That's correct: the approach should be the the client executing a SET default_transaction_read_only TO true (or SET SESSION CHARACTERISTICS if you prefer: they are equivalent as per ). Note that you can also create a by-default-read-only connection by setting the parameter at connection time, using the 'options' connection parameter, for example: >>> conn = psycopg.connect("", options="-c default_transaction_read_only=true", autocommit=True) >>> conn.execute("create table foo ()") Traceback (most recent call last) ... ReadOnlySqlTransaction: cannot execute CREATE TABLE in a read-only transaction >>>conn.execute("select 1").fetchall() # connection is autocommit, so it's not failed [(1,)] > Thank you for your patience with me, Thank you for reporting these documentation shortcomings! Will fix them. Cheers -- Daniele