我正在尝试构建一个小的Rails应用程序,以游戏的形式向初学者教授SQL。它的一部分是一个命令行,用户试图用SQL解决问题。在后端,我想对一个测试数据库运行他们的SQL命令,并检查结果,看看他们的命令是否正确。
我目前的想法是为课程的每个阶段创建sqlite数据库,然后在每个用户到达该阶段时为他们创建该数据库的副本。
我认为这是可行的,但我担心效率。
我的问题是是否有一种有效的方法让用户运行SQL命令(包括drop
、alter
等)。),获得结果,但实际上并不对数据库本身进行任何更改,本质上是任意SQL命令的干运行。我熟悉sqlite和postgres,但对其他数据库持开放态度。
2条答案
按热度按时间lrl1mhuk1#
在Postgres中,你可以对transactions做很多事情,这些事务在最后被回滚:
不要做
COMMIT
!阅读有关
BEGIN
和ROLLBACK
的手册。但是要注意,有些事情是无法回滚的。例如,序列不会回滚。或者一些特殊的命令,比如dblink调用。
并且某些命令不能在与其他命令的事务中运行。例如
CREATE DATABASE
或VACUUM
。此外,并发加载可能会有副作用,如死锁。不过,不太可能。您可以将transaction isolation level设置为您的要求,以排除任何副作用(以性能为代价)。
我不会对敏感数据这样做。意外犯罪的风险太大了。让用户执行任意代码是一种几乎无法控制的风险。但对于一个训练环境来说,这应该足够好了。
用模板数据库备份。如果出了问题,这是恢复基本状态的最快方法。示例(看最后一章):
这也可以用作暴力破解替代:为每个学员提供一个全新的数据库。
whlutmcx2#
虽然您可以在事务中运行它们的代码,然后在回滚之前尝试检查同一事务中的结果,但这会有一些挑战。
首先,如果他们的代码中有任何错误,事务将中止。除了“它失败了,这是错误消息”之外,你什么也说不出来。特别是,您将无法在错误之前检查部分结果。
其次,如果您在单个数据库中进行并行运行,那么锁定会对您造成影响。每个会话将获得锁,通常是元组或整个关系上的排他锁。其他会话将阻止等待锁。这意味着您必须连续地运行测试。这在你的环境中可能不是一个问题,但值得考虑。
第三,正如Erwin所指出的,您必须使检查代码对序列值之类的东西不敏感,因为它们在回滚时不会重置。
基于这些原因,我强烈建议:
...或者省略模板数据库的使用,让Rails应用程序为每个用户使用迁移设置一个空白数据库。这可能更简单,因为这意味着您不必维护模板DB。
一个PostgreSQL服务器可以很好地处理成百上千的数据库,至少如果它不需要在高峰生产负载下运行的话。
您可能需要查看http://sqlfiddle.com/和许多其他现有的基于Web的SQL编辑器/培训工具,其中许多都是开源的。