Ruby 通过DataMapper从SQLite内存数据库中没有这样的表错误

Ruby 通过DataMapper从SQLite内存数据库中没有这样的表错误,ruby,sqlite,datamapper,Ruby,Sqlite,Datamapper,我有一个Ruby程序,它使用DataMapper作为ORM与内存中的SQLite DB对话。这很好,但是我最近添加了一个新的DM类和相应的表。令我惊讶的是,在自动迁移过程中,事情发生了爆炸 以下是DataMapper生成的SQL: ~ (0.000390) PRAGMA table_info("sensationd_channels") ~ (0.000010) PRAGMA table_info("sensationd_commands") ~ (0.000009) PRAGMA table_

我有一个Ruby程序,它使用DataMapper作为ORM与内存中的SQLite DB对话。这很好,但是我最近添加了一个新的DM类和相应的表。令我惊讶的是,在自动迁移过程中,事情发生了爆炸

以下是DataMapper生成的SQL:

~ (0.000390) PRAGMA table_info("sensationd_channels")
~ (0.000010) PRAGMA table_info("sensationd_commands")
~ (0.000009) PRAGMA table_info("sensationd_configurations")
~ (0.000052) PRAGMA table_info("sensationd_measurements")
~ (0.000028) SELECT sqlite_version(*)
~ (0.000035) DROP TABLE IF EXISTS "sensationd_channels"
~ (0.000009) PRAGMA table_info("sensationd_channels")
~ (0.000423) CREATE TABLE "sensationd_channels" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "channel" INTEGER NOT NULL, "name" VARCHAR(50), "precision" INTEGER DEFAULT 11, "gain" INTEGER DEFAULT 1, "differential" BOOLEAN DEFAULT 'f', "configuration_id" INTEGER NOT NULL)
~ (0.000191) CREATE INDEX "index_sensationd_channels_configuration" ON "sensationd_channels" ("configuration_id")
~ (0.000015) DROP TABLE IF EXISTS "sensationd_commands"
~ (0.000009) PRAGMA table_info("sensationd_commands")
~ (0.000153) CREATE TABLE "sensationd_commands" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "action" INTEGER DEFAULT 1, "complete" BOOLEAN DEFAULT 'f', "issued_at" TIMESTAMP, "completed_at" TIMESTAMP)
~ (0.000015) DROP TABLE IF EXISTS "sensationd_configurations"
~ (0.000009) PRAGMA table_info("sensationd_configurations")
~ (0.000155) CREATE TABLE "sensationd_configurations" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "created_on" TIMESTAMP, "modified_on" TIMESTAMP, "name" VARCHAR(50) NOT NULL, "active" BOOLEAN)
~ (0.000015) DROP TABLE IF EXISTS "sensationd_measurements"
~ (0.000009) PRAGMA table_info("sensationd_measurements")
~ (0.000152) CREATE TABLE "sensationd_measurements" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "timestamp" TIMESTAMP, "measurement" VARCHAR(65535) NOT NULL, "channel_id" INTEGER NOT NULL, "channel_configuration_id" INTEGER NOT NULL)
~ (0.000175) CREATE INDEX "index_sensationd_measurements_channel" ON "sensationd_measurements" ("channel_id", "channel_configuration_id")
~ (0.000083) SELECT "id", "created_on", "modified_on", "name", "active" FROM "sensationd_configurations" WHERE "active" = 't' ORDER BY "id" LIMIT 1
~ (0.000073) INSERT INTO "sensationd_configurations" ("created_on", "modified_on", "name", "active") VALUES ('2011-08-01T12:36:18-07:00', '2011-08-01T12:36:18-07:00', 'Test U6-Pro Configuration, differential.', 't')
~ (0.000109) SELECT "id", "action", "complete", "issued_at", "completed_at" FROM "sensationd_commands" ORDER BY "issued_at" DESC LIMIT 1
~ (0.000086) INSERT INTO "sensationd_channels" ("channel", "name", "precision", "gain", "differential", "configuration_id") VALUES (0, '0', 11, 0, 't', 1)
~ no such table: sensationd_commands (code: 1, sql state: , query: SELECT "id", "action", "complete", "issued_at", "completed_at" FROM "sensationd_commands" ORDER BY "issued_at" DESC LIMIT 1, uri: sqlite3::memory:?scheme=sqlite&user=&password=&host=&port=&query=&fragment=&adapter=sqlite3&path=:memory:)
看起来创建表的过程很顺利,但几行之后就找不到了。我会认为我错误地配置了DB连接,除了找到了其他表并且工作正常

正在使用的软件:

  • Ruby 1.9.2p289通过RVM
  • SQLite3@3.7.7.1通过MacPorts
  • DataMapper gem v 1.1.0

有人知道这是为什么吗?我能做些什么吗?

我怀疑,问题在于DataMapper(或者更准确地说,DataObjects,数据库驱动程序DataMapper使用)自动执行的线程池。线程之间不共享数据库连接。这对于postgresql、mysql甚至sqlite3这样的“文件备份”数据库来说都是很好的(甚至是有益的)。对于sqlite3的内存存储,连接是数据库。因此,额外的线程将因此而失败。另外,在一段时间的不活动(~1分钟?)之后,线程将被清除,数据库也将消失


如果是这样的话,我不确定是否有一个简单的解决办法。您可以修改do_sqlite3来避免这种情况。另一个基本上应该同样快的选择是在ramdrive上使用一个文件支持的sqlite3db。

我通过@Lukas_Skywalker的建议复制我的评论作为答案


我知道太晚了,但也许它能帮助别人。您可以使用特殊文件名file::memory:?cache=shared使用内存SQLite共享缓存。这允许单独的数据库连接共享相同的内存中数据库

我也遇到了同样的问题,但没有找到解决方案:(在我的例子中,在进一步修改之后,它看起来可能是一个线程问题。在创建一个新线程后,在一个新线程中访问一个表的速度过快,似乎会导致DataMapper发出SQL,这会使SQLite感到悲伤。稍后在第二个线程中移动数据库访问会使它正常工作,即使记录的SQL序列在两个ca中似乎都有效这听起来很有可能。今天我将通过返回“有问题”来测试DB访问模式,然后在内存和磁盘存储之间交换。我不能绝对肯定这就是问题所在,但如果我从内存存储切换到磁盘存储,并且所有其他代码都相同,那么问题确实会消失。感谢您的帮助!我知道得太晚了,但可能可以帮助某人。您可以使用内存SQLite共享cac他使用了特殊的文件名
file::memory:?cache=shared
。这允许单独的数据库连接共享同一个内存数据库。@Robertiano,您应该将此作为附加答案来写。这里有最有价值的注释。