Php 在同一MySQL事务中删除数据后仍然可见

Php 在同一MySQL事务中删除数据后仍然可见,php,mysql,pdo,transactions,acid,Php,Mysql,Pdo,Transactions,Acid,最近,我一直在测试我的PHP框架的数据库包装器类,它基于PHP数据对象。我已经成功地通过了Oracle数据库的所有测试,并开始使用MySQL进行测试,当时我遇到了一个看起来像恶梦一样的错误 简而言之,我的数据库驱动程序包装类执行以下操作: 1它使用以下属性建立持久数据库连接 self::$connection = new PDO( $dsn ,DATABASE_USERNAME ,DATABASE_PASSWORD ,[

最近,我一直在测试我的PHP框架的数据库包装器类,它基于PHP数据对象。我已经成功地通过了Oracle数据库的所有测试,并开始使用MySQL进行测试,当时我遇到了一个看起来像恶梦一样的错误

简而言之,我的数据库驱动程序包装类执行以下操作:

1它使用以下属性建立持久数据库连接

self::$connection = new PDO( $dsn ,DATABASE_USERNAME ,DATABASE_PASSWORD ,[ PDO::ATTR_AUTOCOMMIT => FALSE // Do not autocommit every single statement ,PDO::ATTR_CASE => PDO::CASE_LOWER // Force column names to lower case ,PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC // Return result set as an array indexed by column name ,PDO::ATTR_EMULATE_PREPARES => (DATABASE_DRIVER == 'mysql') // Allow emulation of prepared statements only for MySQL ,PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION // Throw an exception and rollback transaction on error ,PDO::ATTR_ORACLE_NULLS => PDO::NULL_EMPTY_STRING // Convert emtpy strings to NULL ,PDO::ATTR_PERSISTENT => TRUE // Use persistent connection ] ); 3.到目前为止一切顺利。但让我们看一下下面的示例,该示例对同一个表调用DELETE语句,然后调用SELECT语句,该表具有非常相同的where条件:

database::execute('DELETE FROM dms_test WHERE id = 5'); $data = database::execute('SELECT FROM dms_test WHERE id = 5'); 4每个人都希望SELECT语句返回一个空的结果集,因为前面的DELETE语句刚刚删除了同一事务中的所有数据

5但是,尽管听起来很疯狂,SELECT语句返回非空的结果集,就好像永远不会发出DELETE语句一样

6有趣的是,同一个示例在Oracle数据库中按预期工作

你知道MySQL有什么问题吗?
你们有没有遇到过类似的问题?

我可以通过完全删除PDO的事务机制并用我自己的事务机制替换它来解决这个问题。显然,在禁用MySQL RDBMS和自动提交模式的情况下使用PDO事务机制可能会导致不可预测的行为。我不知道这是PDO还是MySQL错误

如果要使用PDO实现对数据库的开箱即用事务访问,请不要使用PDO的内置PDO::beginTransaction、PDO::commit和PDO::rollback方法

相反,我建议您使用以下方法:

建立连接时,使用属性PDO::ATTR_AUTOCOMMIT=> 假的

通过声明您自己的变量来跟踪处于事务状态的 为此目的,例如,$in_交易

注册关闭函数,该函数在 处于事务状态时请求的结尾


使用这种方法,我能够克服上面提到的错误。

自动提交设置为false,因此除非使用Transaction、commit或rollback提交更改,否则不会保存任何更改
PDO::ATTR_AUTOCOMMIT=>FALSE

PDO::beginTransaction关闭自动提交模式。关闭自动提交模式时,通过PDO对象实例对数据库所做的更改不会提交,直到您通过调用PDO::commit结束事务。调用PDO::rollBack将回滚对数据库的所有更改,并将连接返回到自动提交模式。在这里发布之前请阅读手册。您的dms_测试表使用哪种MySQL存储引擎?MyISAM存储引擎缺乏对事务的支持。这可以解释你的问题。每个理智的人都在变得非常个人化。这只是免费软件,就像小猫一样免费,就像我们在这里谈论的啤酒一样免费。恕我直言,放轻松点!大安,恕我直言,在让我阅读手册之前,请先阅读我的帖子。自动提交模式从未启用过,它已使用连接属性关闭。请参见第1点。其次,你还没有读到我说过的,在Oracle上同样的代码可以很好地工作,见第6点。第三个问题是MySQL RDBMS返回的结果集不应该在同一事务中,-注意DELETE在SELECT之前。在本例中,还发出了nor COMMIT和ROLLBACK。Ollie Jones,不,我当然没有使用MyISAM,因为它缺乏基本的ACID合规性。我看不出你的代码中有什么特别错误的地方,我也无法想象会发生这样的情况。我可以建议您记录查询以排除明显的问题吗? database::execute('DELETE FROM dms_test WHERE id = 5'); $data = database::execute('SELECT FROM dms_test WHERE id = 5');