我在尝试为我的应用程序实现一些计数器时遇到了这种奇怪的行为。 基本上,我做了一个像这样的柜台:
CREATE TABLE stats_dev.log_counters (
date text PRIMARY KEY,
all counter
);
然后我也想计算一些特定类型的消息,因此在我的 Go 应用程序中,我更改了表格以添加以前没有的列。
我的应用程序正在不断增长,我开始拥有超过 30 列(不应超过 50 列),当我想要检索所有这些计数器时,结果中缺少一些列。
query := s.Query(`SELECT * FROM `+_apiCountersTable+` WHERE date IN ?`, dates)
res, err := query.Iter().SliceMap()
这会返回 34 列中的 30 列。虽然,当我在 CQLSH 上执行请求时:
cqlsh:stats_dev> SELECT * FROM api_counters WHERE date = 'total';
我得到了正确的完整结果。所以:
- 这是否来 self 的要求,应该有所不同?
- 这可能来自 gocql司机?
- 这种模式完全愚蠢吗?
我的临时解决方案是从 system.schema_columns
表中 SELECT 列名称,并将所有这些添加到 strings.Join() 到我的 SELECT 查询中...
非常感谢您的帮助。
最佳答案
我不熟悉 gocql 库,但听起来您可能会遇到不重新准备语句和 CASSANDRA-7910 的组合。 .
每当一个请求准备好时(比如 Select * from ___ where date in 中正在做什么?),它会向 cassandra 发送一个请求,cassandra 会使用该表的列元数据进行响应,因此当您收到对从 cassandra 查询回来,您知道可以查找哪些列。看起来 gocql 有一个名为“自动查询准备”的功能,它可能会将您的请求视为准备好的语句。
当您更改表时,准备好的语句不会在客户端更新,因此解决此问题的唯一方法是重新准备语句(不确定您是否具有 gocql 的控制级别)。然而,这仍然不起作用,因为 cassandra ( CASSANDRA-7910 ) 中存在一个错误,它不会返回新列,因为它本身会在其一侧缓存准备好的语句,并且在架构更改时不会使其无效。此问题已在 2.1.3 中修复(即将推出),可能值得在 git 中的 cassandra-2.1 分支上尝试此操作,看看是否可以解决您的问题。
在应用程序运行时更改架构并不是一种异常模式,因此这种情况应该可行,但不幸的是不行。我会研究是否有一种方法可以在 gocql 中重新准备语句。
我看到 cluster.go 中有一个 stmtsLRU
var。如果你能以某种方式做到这一点,你就可以使准备好的语句无效。如果没有办法做到这一点,最好针对 gocql 提出问题,因为您可以在其他驱动程序中再次重新准备语句。我知道java驱动程序允许你这样做,但会给你一个警告。我想这可能是 gocql 和其他驱动程序之间的一个很大的区别,因为在其他驱动程序中,您显式使用准备好的语句对象,而在 gocql 中,它会在库中自动为您处理。
由于 cassandra bug 很突出,我认为您应该坚持不使用准备好的语句,而是进行如下查询:SELECT * FROM api_counters WHERE date = 'total';
关于gocql SELECT * 不返回所有列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28033756/