暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

CockroachDB TIL:第6卷

原创 eternity 2022-08-12
796

这是我的系列文章,涵盖了我在处理CockroachDB时的简短“今天我学到了”主题。

主题1:Cockroach初始化容器

使用init容器初始化Cockroach并退出,当您启动CockroachDB时,您不再需要显式运行init。

version: '3.9'

services:

  roach-0:
    container_name: roach-0
    hostname: roach-0
    image: cockroachdb/cockroach:v21.2.4
    command: start --logtostderr=WARNING --log-file-verbosity=WARNING --insecure --join=roach-0,roach-1,roach-2 --listen-addr=roach-0:26257 --advertise-addr=roach-0:26257 --max-sql-memory=.25 --cache=.25
    ports:
      - 26257:26257
      - 8080:8080
    healthcheck:
      test: ["CMD", "curl", "http://roach-0:8080/health?ready=1"]
      interval: 2s
      timeout: 1m
      retries: 5
      start_period: 10s

  roach-1:
    container_name: roach-1
    hostname: roach-1
    image: cockroachdb/cockroach:v21.2.4
    command: start --logtostderr=WARNING --log-file-verbosity=WARNING --insecure --join=roach-0,roach-1,roach-2 --listen-addr=roach-1:26257 --advertise-addr=roach-1:26257 --max-sql-memory=.25 --cache=.25
    ports:
      - 26258:26257
      - 8081:8080
    healthcheck:
      test: ["CMD", "curl", "http://roach-1:8080/health?ready=1"]
      interval: 2s
      timeout: 1m
      retries: 5
      start_period: 10s
    
  roach-2:
    container_name: roach-2
    hostname: roach-2
    image: cockroachdb/cockroach:v21.2.4
    command: start --logtostderr=WARNING --log-file-verbosity=WARNING --insecure --join=roach-0,roach-1,roach-2 --listen-addr=roach-2:26257 --advertise-addr=roach-2:26257 --max-sql-memory=.25 --cache=.25
    ports:
      - 26259:26257
      - 8082:8080
    healthcheck:
      test: ["CMD", "curl", "http://roach-2:8080/health?ready=1"]
      interval: 2s
      timeout: 1m
      retries: 5
      start_period: 10s

  init:
    image: cockroachdb/cockroach:v21.2.4
    command: init --insecure --host=roach-0

当docker compose出现时,您可以观察到以下情况:

oach-1   | *
roach-1   | * INFO: initial startup completed.
roach-1   | * Node will now attempt to join a running cluster, or wait for `cockroach init`.
roach-1   | * Client connections will be accepted after this completes successfully.
roach-1   | * Check the log file(s) for progress. 
roach-1   | *
5-init-1  | Cluster successfully initialized
roach-0   | W220121 20:03:55.536091 72 2@gossip/gossip.go:1486 ⋮ [n?] 4  no incoming or outgoing connections
5-init-1 exited with code 0
roach-2   | W220121 20:03:55.781539 48 2@gossip/gossip.go:1486 ⋮ [n?] 4  no incoming or outgoing connections
roach-0   | CockroachDB node starting at 2022-01-21 20:03:55.7840506 +0000 UTC (took 1.1s)
roach-0   | build:               CCL v21.2.4 @ 2022/01/10 18:50:15 (go1.16.6)
roach-0   | webui:               http://roach-0:8080
roach-0   | sql:                 postgresql://root@roach-0:26257/defaultdb?sslmode=disable
roach-0   | sql (JDBC):          jdbc:postgresql://roach-0:26257/defaultdb?sslmode=disable&user=root
roach-0   | RPC client flags:    /cockroach/cockroach <client cmd> --host=roach-0:26257 --insecure

更具体地说:

5-init-1  | Cluster successfully initialized
5-init-1 exited with code 0

主题2:链列的模式更改为单个语句

考虑以下两种模式:

CREATE TABLE tbl (
    key UUID DEFAULT gen_random_uuid() PRIMARY KEY,
    col1 STRING,
    col2 STRING
);

对于change语句,在一行上执行这两条语句更有效。这样,CockroachDB将在单跳中执行语句。

ALTER TABLE tbl ALTER COLUMN col1 SET NOT NULL;
ALTER TABLE tbl ALTER COLUMN col1 SET DEFAULT '';

您可以将这两条语句包装在显式事务中,并在将批处理作为单个块执行方面获得一些效率。

BEGIN;
ALTER TABLE tbl ALTER COLUMN col1 SET NOT NULL;
ALTER TABLE tbl ALTER COLUMN col1 SET DEFAULT '';
COMMIT;

也许有更好的方法,我们可以将schema change语句重写为单个语句,并添加后续的列更改,包括用逗号分隔的不同列。

ALTER TABLE tbl ALTER COLUMN col1 SET NOT NULL, ALTER COLUMN col1 SET DEFAULT '', ALTER COLUMN col2 SET NOT NULL;

主题3:关闭fsync(不安全)

对于是否包括下一个技巧,我持谨慎态度,因为这会对生产环境产生严重影响。然而,对于数据不相关的本地开发,它可以产生一些效率和性能。CockroachDB依靠fsync刷新磁盘上的数据,因此速度也很慢也就不足为奇了。考虑主题2的示例:

ALTER TABLE tbl ALTER COLUMN col1 SET NOT NULL, ALTER COLUMN col1 SET DEFAULT '', ALTER COLUMN col2 SET NOT NULL;

命令的输出:

root@:26257/test> ALTER TABLE tbl ALTER COLUMN col1 SET NOT NULL, ALTER COLUMN col1 SET DEFAULT '', ALTER COLUMN col2 SET NOT NULL;
ALTER TABLE

Time: 382ms total (execution 382ms / network 0ms)

此语句的执行统计信息不表示任何缓慢。考虑到我使用的是Macbook,我们的工程师建议关闭fsync,考虑到其影响!

SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = true;
root@:26257/test> SET CLUSTER SETTING kv.raft_log.disable_synchronization_unsafe = true;
SET CLUSTER SETTING

Time: 111ms total (execution 111ms / network 0ms)

root@:26257/test> ALTER TABLE tbl ALTER COLUMN col1 SET NOT NULL, ALTER COLUMN col1 SET DEFAULT '', ALTER COLUMN col2 SET NOT NULL;
ALTER TABLE

Time: 29ms total (execution 29ms / network 0ms)

事情马上就快多了。同样,请小心使用!

主题4:将.pgpass与Java pgjdbc驱动程序一起使用

Pgjdbc 42.3.0版添加了一个选项,用于读取.pgpass文件和/或环境变量PGPASSFILE的内容。这让我非常高兴,因为我认为任何能从窥探者的眼睛中获得密码的机会在我的书中都很酷。

我们需要的是设置.pgpass文件。您可以在我的第二篇TIL文章主题2中找到说明。此时,我们需要一个Java程序。让我们在文档中使用示例Java应用程序。具体来说,我们将使用JDBC/Serverless步骤。这些步骤还将引导您完成本主题中使用的无服务器集群的设置。

git clone https://github.com/cockroachlabs/example-app-java-jdbc/
cd example-app-java-jdbc
git checkout cockroachcloud

转到初始化数据库步骤,运行指向集群的命令

cat app/src/main/resources/dbinit.sql | cockroach sql --url "<connection-string>"

为了简单起见,我将连接字符串保存在环境变量$COCKROACH_URL中,如TIL第2卷主题1中所述。

cat app/src/main/resources/dbinit.sql | cockroach sql --url $COCKROACH_URL

在运行代码之前,我们需要更新连接参数。与文档中的教程不同,我们将有意省略password属性。

ds.setServerNames(new String[]{"free-tier14.aws-us-east-1.cockroachlabs.cloud"});
        ds.setPortNumbers(new int[]{26257});
        ds.setDatabaseName("artem-serverless-480.bank");
        ds.setSsl(true);T
        ds.setUser("artem");
        //ds.setPassword("{password}");

最后,我们需要更新依赖文件以使用最新的pgjdbc驱动程序,在编写本文时,该驱动程序是42.3.3。

您可以在./example-app-java-jdbc/app/build.gradle中找到该文件。

 dependencies {
     // This dependency is used by the application.
     implementation 'com.google.guava:guava:29.0-jre'
-    implementation 'org.postgresql:postgresql:42.2.18'
+    implementation 'org.postgresql:postgresql:42.3.3'
 }```

At this point, we're ready to run the code. The driver will either read the contents of the `.pgpass` file, property `-Dorg.postgresql.pgpassfile=filename` or `PGPASSFILE=` environment variable. Let me show you each way:

This is a gradle project, passing an environment variable to the project looks like so:

```bash
PGPASSFILE=/tmp/.pgpass ./gradlew run

我使用一个临时目录来说明这一点,默认情况下,驱动程序将读取$HOME/.pgpass的位置。

> Task :app:run

com.cockroachlabs.BasicExampleDAO.updateAccounts:
    'INSERT INTO accounts (id, balance) VALUES ('fc4da00e-1240-4578-9bdb-aaf873c61ba8', 250)'

com.cockroachlabs.BasicExampleDAO.updateAccounts:
    'INSERT INTO accounts (id, balance) VALUES ('e469ce3a-2352-47a7-b79e-a8f7fa3eb6ab', 1000)'
BasicExampleDAO.updateAccounts:
    => 2 total updated accounts
main:
    => Account balances at time '17:32:20.237880':
    ID 1 => $1000
    ID 2 => $250

com.cockroachlabs.BasicExampleDAO.transferFunds:
    'UPSERT INTO accounts (id, balance) VALUES('2d89869e-f274-4d21-b538-b2440c4f94fd', ((SELECT balance FROM accounts WHERE id = '2d89869e-f274-4d21-b538-b2440c4f94fd') - 100)),('75473622-9889-4cfb-9c32-30dba19ae116', ((SELECT balance FROM accounts WHERE id = '75473622-9889-4cfb-9c32-30dba19ae116') + 100))'

到目前为止,一切都很好。让我们用Java参数来运行它。为此,我们将编辑相同的版本。gradle文件并添加新行。

application {
     // Define the main class for the application.
     mainClass = 'com.cockroachlabs.BasicExample'
     applicationDefaultJvmArgs = ['-Djdk.tls.client.protocols=TLSv1.2']
+    applicationDefaultJvmArgs = ['-Dorg.postgresql.pgpassfile=/tmp/.pgpass']
 }

再次运行以验证。

./gradlew run

最后,删除参数并将.pgpass文件放回$HOME中。完成后,再次运行代码,不传递任何参数。它应该成功完成。

对于后代来说,如果我们无法从文件中读取密码,情况会是这样:

> Task :app:run
BasicExampleDAO.runSQL ERROR: { state => 08004, cause => null, message => The server requested password-based authentication, but no password was provided by plugin null 

主题5:使用cockroach demo避免积垢

cockroach demo是帮助演示cockroach 数据库功能的宝贵工具。另一种方法是使用–store=type=mem命令启动内存中的cockroach 数据库实例,而不保存任何数据。我对这两个选项的不满是,当你旋转其中一个时,它们会在目录中留下剩余的文件。在演示中,您将找到inflight_trace_dump,在–store=type=mem的情况下,您还将找到heap_profiler和goroutine_dump。避免创建这些目录的方法是将目录设置为只读,这两种方法仍然有效。

mkdir readwrite && cd readwrite

cockroach start-single-node --insecure --store=type=mem,size=0.25 --advertise-addr=localhost --background

在另一个终端中,发出ls-ltra读写:

drwx------@ 464 artem  staff  14848 Mar  7 15:28 ..
drwxr-x---    2 artem  staff     64 Mar  7 16:43 inflight_trace_dump
drwxr-x---    2 artem  staff     64 Mar  7 16:43 goroutine_dump
drwxr-xr-x    5 artem  staff    160 Mar  7 16:43 .
drwxr-x---    6 artem  staff    192 Mar  7 16:44 heap_profiler

您可以在演示中尝试同样的方法,您会注意到inflight_trace_dump目录。

停止进程,pkill cockroach,现在让我们尝试使用只读目录:

mkdir readonly
chmod -w readonly
cd readonly
cockroach start-single-node --insecure --store=type=mem,size=0.25 --advertise-addr=localhost --background

在另一个终端中,发出ls-ltra readonly:

➜  readonly ls -ltra
total 0
dr-xr-xr-x    2 artem  staff     64 Mar  7 15:26 .
drwx------@ 464 artem  staff  14848 Mar  7 15:28 ..

原文标题:CockroachDB TIL: Volume 6
原文作者:Artem Ervits
原文链接:https://dzone.com/articles/cockroachdb-til-volume-6

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论