我在工作中一直在玩Vitess,我发现在谷歌上查找Vitess的常见问题和错误信息非常困难。虽然官方文档在不断改进,但普遍缺乏类似堆栈溢出的提示来解决愚蠢的错误。我决定在这篇文章中保留我自己的日志,部分是为了自己。
CI上的Vitess
Vitess提供了一个测试服务器,让你可以快速地在CI上运行它或用于本地开发。我发现它非常容易运行,而且效果非常好。
下面是我的同事Hormoz和我一起制定的docker-compose片段。
# docker-compose format
services:
vttest:
image: vitess/vttestserver:mysql57
command:
- "/vt/bin/vttestserver"
- "-alsologtostderr"
- "-port=2222"
- "-mysql_bind_host=0.0.0.0"
- "-vschema_ddl_authorized_users=%"
# comma-separated list of keyspaces
- "-keyspaces=unsharded,sharded,archive"
# number of shards per each keyspace
- "-num_shards=1,2,1"
# in case you want to mount vschema definitions:
# - "-schema_dir=/db/vitess/schema"
填充模式
为了在CI上运行测试,你需要在Vitess实例中填充模式。至少有两种方法可以做到这一点。
- 最简单的方法:通过
vschema.json进行填充- 你可以选择通过
-schema_dir,并挂载一个目录,该目录将有一个匹配的层次的关键空间名称和vschema.json
- 你可以选择通过
- 用DDL手动填充
- 你也可以选择让你自己的脚本在测试服务器上执行
alter vschema和create table。 - 这有点复杂,但如果你想让表的集合是动态的,则提供了灵活性。
- 你也可以选择让你自己的脚本在测试服务器上执行
- 通过CLI与
vtctl ApplyVSchema- 这将需要
vtctl,而在你的应用程序的CI容器中通常不是这样的。
- 这将需要
VSchema DDLs
如果你试图在测试服务器上运行alter vschema ,你可能会遇到。
> alter vschema add table sharded.products;
ERROR 1045 (HY000): vtgate: http://a90e850de0ed:2222/: not authorized to perform vschema operations
你要用这个标志来运行测试服务器,以允许任何用户操作vschema。
-vschema_ddl_authorized_users=%
vschema.json中的错误
如果你决定通过挂载一个vschema.json 文件来填充VSchema,在一个畸形的JSON模式上,你会看到进程崩溃,出现类似的错误。
main.go:162] initTabletMapProto failed: cannot load vschema file /schema/sharded/vschema.json for keyspace sharded: json: cannot unmarshal object into Go value of type []json.RawMessage
虽然那里的东西给了你一个指针,即JSON不能被匹配成Go值,但我发现这个错误相当令人困惑,我不得不导航到Vitess源,以查找JSON被期望是什么模式/protobuf。这让我发现,在我的例子中,本应是数组的东西却成了地图。
让应用程序为分片做好准备
如果你正在将现有的应用程序植入Vitess,你可能会有一些查询失败,因为它们还没有准备好被分片,或者与Vitess不兼容。
Minitest::UnexpectedError: ActiveRecord::StatementInvalid: Mysql2::Error: vtgate: unsupported: You can't update primary vindex columns. Invalid update on vindex: hash
app/models/product.rb:253:in `publish'
更加难以调试的是,你看不到失败的完整SQL查询。由于我是在Rails应用中实现的,所以我在Rails中加入了以下仅适用于CI的补丁,以记录vtgate上所有失败的查询。
module ActiveRecord
module ConnectionAdapters
class AbstractAdapter
module VitessErrorLogger
def log(sql, *args, &block)
super(sql, *args, &block)
rescue Mysql2::Error => error
if error.message.include?("vtgate")
puts "[VITESS] #{error}"
puts "[VITESS] Full sql:\n#{sql}"
end
raise
end
end
prepend AbstractAdapter::VitessErrorLogger
end
end
end
我可能会用我遇到的更多事情来刷新这个帖子。