Soooo - I spent some time reading the PostgreSQL manual. Please bear with me if I get too picky about details here. Also the text got quite lenthy.
First of all: Zeos Works in Read Committed isolation [1]:
PostgreSQL 9.6 Manual, Section 13.2.1. Read Committed Isolation Level: wrote:Read Committed is the default isolation level in PostgreSQL.
You simply will not get any lower transaction isolation with PostgreSQL. [2]:
PostgreSQL 9.6 Manual, Section 13.2. Transaction Isolation: wrote:In PostgreSQL, you can request any of the four standard transaction isolation levels, but internally only three distinct isolation levels are implemented, i.e. PostgreSQL's Read Uncommitted mode behaves like Read Committed.
But then Zeos doesn't use the PostgreSQL supplied AutoCommit and implements its own on top of PostgreSQL. This doesn't always work flawless, I have to admit. This is documented in the Wiki page that I referenced to in an earlier post.
What you do by using tiNone is bypass the Zeos transaction control, get PostgreSQL AutoCommit that way and then you implement your own transaction control on top of that by using ExecuteDirect.
Honestly I doubt that you will save much ressources by that. This is because PostgreSQL also needs to manage its transactions. I suggest you read up on MVCC. At least for firebird there is quite some documentation about MVCC and that will answer the question why MVCC will never work without transactions.
So - what can PostgreSQL do. In the first case it will create a transaction right after connection and commit that after it receives and execute a command. Afterwards it has to create the next transaction. In this model you would have a similar consumption of ressources as you would have with Zeos because there always is a transaction. In a second case it could create the transaction right when it receives the command, start the transaction, execute the command and commit or rollback that transaction immediately after the command finishes. In that case the ressource consumption on the server would be slightly lower than by the things Zeos currently does. But then - I doubt that the ressources you can save by your approach will be worth the extra time that you have to invest by building your own transaction control.
Bottom line: I have to recheck that, but as far as I know the current implementation of the Zeos Components and the DBC layer have no concept to know wether the components need to simulate AutoCommit mode for a database or wether a database can handle that on its own. So it will not be easy to extend them and make things work for all other supported databases. With the current implementation of prepared statements this extension is a must have for the release of prepared statements.
Releasing prepared statements at the beginning of a new transaction has its reasons, it was a bug fix. In an earlier implementation statements were released as soon as possible. Unfortunately this lead to errors when statements in an transaction raised an error. If a statement fails to execute properly PostgreSQL will mark that Transaction as being failed. In failed transactions one cannot do anything besides rolling them back. You can't release prepared statements. This could lead to problems in Applications using Zeos because Zeos would sometimes try to release a statement in an transaction that is in a failed state. The application then wouldn't see the original Exception but it only would see an exception that you can't do anything in a failed transaction. There was no way to find out what caused the transaction to fail.
As a counter measure I moved the release of prepared statements to the start of a new transaction, because there we could be sure that the transaction is in a good state. Case solved.
Well - it seems, that introduced a new case since tiNone will not use the PostgreSQL DBC transaction support and by this statements will never get freed. There is one way out of this for me. We need to implement a way where stetements can be released either immediately or where the release of transactions can be postponed. Then there are two ways to implement that.
Way one: Implement a way of tracking if a transaction is in a healthy state or wether it is failed. Release statements immediately while the transaction is healthy, postpone the release of statements until the start of the next transaction if the transaction is failed. This seems quite hard for me to achieve, because honesly I have no idea on how to do that in a good way where I don't need to modify one gazillion places all over the dbc driver. Also it seems error prone to me.
Way two: Always release statements in the next transaction. Only release them immediately if the PostgreSQL AutoCommit is in use currently. This seems like the better idea to me. It is more close to the current implementation, I have an idea on how to achieve that. But it is time consuming because it will require for the DBC layer and the Components to be modified to have a common view on how to handle AutoCommit mode. Ideally the DBC layer would inform the components if it can do AutoCommit on its own. Then the components would know if they had to do an emulation or not. This also has the added benefit that Zeos could learn on how to make use of the AutoCommit of the underlying databases. tiNone would translate to tiReadCommitted for PostgreSQL - they would both behave the same - as PostgreSQL does anyway.
Since both soluions require quite some time, that I cannot spend currently, what do we do in the short term? My suggestion is to disable tiNone for PostgreSQL. Raise an exception if somebody tries to use it so the programmer will know he tries to do something unsupported. Additionally create a ticket in the Bugtracker that explains on how things should be fixed in the long term. A ticket like that was already created by me because I want to have the abililty to use the database supplied AutoCommit mode, if it exists. It will save round trips to the database if it can be leveraged and should not suffer some of the bugs that the current implementation has. We could extend it to say that tiNone needs to be reenabled for PostgreSQL. The problem is - this would destroy your application in the short term.
So - what is your opinion? If you would take on the challenge of implementing a good solution, I think you and Zeos can benefit from that. Otherwise you will have to wait until I have the time to implement it myself.
[1]:
https://www.postgresql.org/docs/9.6/static/transaction-iso.html#XACT-READ-COMMITTED
[2]:
https://www.postgresql.org/docs/9.6/static/transaction-iso.html