Join GitHub today
Wrong transaction management #50
Still need to confirm and create test script, but looks like if during a PDO transaction if a PDO exception is thrown (even if the exception is catched by the user) the transaction will automatically rollback.
If the 'DO SOMETHING ELSE' throws ann exception, the transaction is rollbacked.
This was not happening without buffered queries.
Here you go. Simple repro script! The driver is automatically doing rollbacks when a PDO exception is thrown, even if the exception is catched by the user.
It would be great if you could look at this ASAP and at least confirm that it can be reproduced,
referenced this issue
Sep 4, 2015
Jason, can you answer Davvid's question?
From: Davvid <email@example.com:firstname.lastname@example.org>
Can you confirm if the repro script worked?
I'm insisting on this because it is potentially affecting the only maintained Drupal-MSSQL integration with loss of data.
Thanks for your time.
Reply to this email directly or view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fAzure%2fmsphpsql%2fissues%2f50%23issuecomment-139776709&data=01%7c01%7clfsantos%40microsoft.com%7c225b65cccadc47d9707d08d2bb8014bd%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=R2TiAV2LL8g8UE%2fVGSX3JGqMXpRUo9HBqJ98%2bLdmr9M%3d.
Please, feedback on this. I've double checked the repro script and unless there is a flaw that I cannot see in it, this a very nasty PDO driver bug.
Just noticed that the script fails if the table 'PEOPLE' does not exist in the database when it tries to DROP and RECREATE.
Just comment the DROP statement on the first run of the test, or put the DROP inside a try/catch.
@david-garcia-garcia I got an answer from the driver authors. Let me know if this helps:
According to the experts, from the PHP script perspective, it may SEEM like this is a loss of data issue, and, depending on how the transaction is treated, it could lead to data processing errors, PDO and our driver underneath are acting exactly as they should/are designed to.
In the event of an error, uncommitted batched data is automatically rolled back. This behavior is described here: http://php.net/manual/en/pdo.transactions.php, and is congruous with the way that SQL Server works. The following SQL script also demonstrates the behavior in a less abstract form than the PHP script:
The results for the above queries are as follows:
Please let me know if this clarifies anything, if not we will further try to figure out how we can make it better. Additionally, would it be possible for you to get on a call with us? We want to get a better understanding of some of the issues you are facing and help you out.
@meet-bhagdev Thanks for looking into the issue!
Amazingly, I was not expecting this:
There is a fundamental and critical difference between my sample script and the SQL script you posted. Your SQL script is never reaching the COMMIT TRANSACTION because an exception is thrown on the previous SQL statement. If you enclose the failing statement inside a TRY CATCH block, when calling COMMIT TRANSACTION you at least get an error:
But on the PHP side (my sample script) you can call commit and anything done after the first PDOException is actually commited.
Even though this might be an expected behaviour or MSSQL limitation, the driver SHOULD be complaining with a PDOException when $connection->commit() is being called with a message such as this one:
The fact that it silently swallows the $connection->commit() makes this a very dangerous situation. It is not only swallowing the commit() statement but it actually does commit any further operations done inside the scope of the original transaction as if nothing had happened!
I did some tests and it looks like internally the driver is rolling back the transaction and starting a new one. This is unreliable, confusing and error prompt.
Assuming this is an expected behaviour (some PDOExceptions will DOOM the current transaction even if inside a TRY-CATCH block), some other things are wrong:
And still, after reading the PDO documentation link you provided:
I believe it does not match the driver behaviour (but I understand this might be a MSSQL limitation).
This is what it says:
In the provided sample script the connection is not closed netiher the script has ended.
Unluckily I can simply not deal with this behaviour and I am sure (not tested though) this is not happening on MySQL. I maintain the Drupal SQL Server integration, but not 3d party code such as core or contrib that might rely on PDO Exceptions thrown inside a TRY-CATCH block not to doom the whole transaction.
As I see this there are 2 things that need to be done here:
1 - Make sure that the PDO driver will not allow calls to $connection->commit() after the transaction is doomed. The provided sample script should be throwing a PDO exception when commit() is called. Se the proposed error message (that is already used by SQL Server).
Indeed, I would not even wait for the call to commit(). Any further attempt to issue an SQL Statement after the transaction is doomed (something that the user is of course not aware of) should throw an exception so that the user inmediately knows that something went wrong.
Fixing this will, at least, make the driver behave in a consistent, safe and understandable manner.
This is extremely important and high priority because, right now, I don't know how many 3d party code is relying on PDOExceptions inside Try-Catch blocks expecting this not to doom the whole transaction. If the driver threw an exception on such a situation, at least I will not get inconsistent data (or loss of data).
2 - WIth more time, see if it will be possible to make PDOExceptions inside Try-Catch blocks not to completely mess up the enclosing transaction. After all, that is why the user is using a Try-Catch block....
As my english permits :) I barely have 2 hour time difference from Redmond, just drop me a private message on my Drupal contact form if you feel this is really necessary (https://www.drupal.org/u/david_garcia). I already have direct e-mail contact with other MS-PHP related teams.
Hi @david-garcia-garcia ,
Is this the contact form I should use to schedule a call? http://www.drupalonwindows.com/en/content/contact
I am also adding @Lfsantos as he may have something to add here.
@meet-bhagdev No that's my hobby site :)
This is the Drupal.org profile:
You need to be registered in Drupal.org to see the contact form and be able to contact another Drupal.org member.
But... use this instead:
deivid dot garcia dot garcia at gmail dot com
I am able to "workaround" the issue by proxying all over both PDOStatement and PDO class and detecting when this messy situation takes place.
All PDO Exceptions are equal, but some are more equal than others :)
Basically, not every kind of PDO Exception will trigger the issue (automatic rollback and issue of new transaction).
Is there a consistent way (such as a specific code list) of knowing which PDO Exceptions trigger the issue?
referenced this issue
Mar 7, 2017
Any news on this?