如何从browsergame设计数据库访问

时间:2012-10-19 09:48:26

标签: php mysql ajax postgresql pdo

首先是一点点背景: 我正在写一个浏览器游戏,练习我的网络技能和乐趣:)有些用户拥有一些工厂和一个主要的仓库。它们产生不同类型的产品,这些产品存储在内部工厂中。用户可以“聚集”工厂,将成品转移到他们的主仓库。

为了实现,我使用PHP和PDO作为数据库连接器。我的网络服务器使用MySQL数据库,我用于调试我使用本地Postgres数据库。

用户应该能够收集所有工厂而无需单击收集链接并等待响应。因此,我使用Ajax,以便用户可以单击所有工厂一次,并等待所有请求完成。为了防止这种并行访问在我的数据库中引入不一致,我使用隔离级别为SERIALIZABLE的事务。因为pdo不支持隔离级别,所以我使用

发送与Postgres-db的连接查询
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET statement_timeout=10000;

第二个查询应该阻止并行事务取消,而另一个事务正在进行中。两个查询都不返回错误,但不起作用。当我发送8个几乎并行的请求时,只有2-3个返回成功,另一个从postgres“25P02 IN FAILED SQL TRANSACTION”返回错误。虽然调试在我看来,交易不等待另一个完成,但我不确定这个。

现在我的问题:

  1. 是否有可能获得与PDO一起使用的隔离级别和超时?
  2. 我可以使用其他替代品吗? (除了像Zend这样的重量级框架,我想从深处探索所有机制)
  3. 如果我只使用一种类型的数据库和像mysqli这样的特殊连接器,我可以解决我的问题吗?我认为使用PDO更灵活是个好主意,但也许这对浏览器游戏来说并不好。
  4. 我的数据库访问方法是否正常?还是有更好的设计?
  5. 此类错误是否正常,此类交易应该循环直至成功?什么时候,在客户端使用Ajax或在服务器端使用PHP?

1 个答案:

答案 0 :(得分:1)

该错误告诉您在已经出错的事务中发出语句。虽然早先的陈述似乎没有失败,但他们可能会这样做; PDO和PHP没有注意到强大而仔细的错误处理。

我强烈建议您在运行测试时检查PostgreSQL日志文件。看看失败的地方和地点。设置log_line_prefix可能会有所帮助,这样您就可以通过显示后端进程ID更轻松地查看哪些语句来自哪些会话,例如:

log_line_prefix = 'ss=%e pid=%p cmd=%i'

您可能还想设置log_statement = all

您很可能会看到PDO发出的查询产生错误,因此您的下一个语句会尝试在中止的事务中执行并生成25P02 in_failed_sql_transaction


BTW,这似乎不是特别需要SERIALIZABLE隔离才能获得一致结果的用例。您是否考虑过只使用UNION ALLSELECT两个?{/ p>
SELECT 'internal', count(inventory_items) FROM internal_inventory
UNION ALL
SELECT 'main', count(inventory_items) FROM main_inventory;

或者如果架构更好:

SELECT isinternal, count(inventory_items)
FROM inventory
GROUP BY isinternal;