如何解决ClickHouse的表处于只读状态

在使用ClickHouse的过程中,经常会遇到某个副本的表A处于readonly状态,无法更新数据。

<Error> executeQuery: Code: 242, e.displayText() = DB::Exception: Table is in readonly mode

原因:说是zookeeper的压力大(建议data和log分开存储到不同的磁盘),metadata元数据丢失。

此时通常有两种解决办法:

1)创建一个和该表A结构相同的表A',然后将数据从A表导入到A',多个副本A'的数据会自动同步,以后使用A'表,涉及使用A表的地方都需要修改为A'表;

2)DEATCH掉A表,重新创建A表,但此时数据不会自动同步,需要人工从其它副本A表导入。

查询哪些副本表处于readonly状态:

select table,zookeeper_path,replica_path from `system`.replicas where is_readonly

对于第二种方法,若DEATCH失败,则只能将该节点停止,并备份该节点的数据(如:mv /var/clickhouse /var/clickhouse_bak),重新启动该节点,会自动创建/var/clickhouse目录,创建新的数据库(如:ksdb),并在此库基础上ATTACH/Create table和Create view(相当于重建节点),然后让集群自动从其他节点同步数据,若无法自动同步,则需要手工进行从其他副本导入。

附1:ATTACH语句案例

--ATTACH 语句

ATTACH TABLE ksdb.client_local (
`userid` String,
 `name` String,
 `type` String,
 `timestamp` Date DEFAULT toDate(now())
) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{layer}-{shard}/client_local', '{replica}') PARTITION BY toYYYYMM(timestamp) ORDER BY userid SETTINGS index_granularity = 8192;

附2: 手工导入语句案例

insert into ksdb.client_local select * from remote('192.168.242.152:9000',ksdb.client_local)

补充第三种解决办法,只重建处于readonly状态的当前表:

#通用方式,在当前节点
#删除表数据
rm -rf  clickhouse/data/database名/表名
#删除表元数据
rm -rf clickhouse/metadata/database名/表名.sql
#./zkCli.sh 连接ZooKeeper,删除其分片对应的副本
rmr /clickhouse/tables/分片名/表名/replicas/副本名
#删除以上数据后,重启该节点,重新CREATE TABLE,数据会自动从其它副本同步过来
#举例如下:
rm -rf  clickhouse/data/ksdb/client_local
rm -rf clickhouse/metadata/ksdb/client_local.sql
./zkCli.sh
rmr /clickhouse/tables/152-01/client_local/replicas/worker1

总结:

第一种方法:数据能自动同步,但需要修改表名,对应用程序不友好;

第二种方法:若DETACH成功,则比较方便;若DETACH失败,则需要重建节点;

第三种方法:是最优的一种方法,只能针对当前处于readonly状态的表,不用改名,也不用重建节点,但要注意不要删错了。

ClickHouse 中,若需要将某个设置为只读状态,可以通过修改的配置或文件系统权限来实现。以下是几种常见的方法: ### 方法一:使用 `ALTER TABLE ... MODIFY SETTING` 设置只读 ClickHouse 支持通过修改的设置来限制写入操作。可以使用以下语句将设置为只读模式: ```sql ALTER TABLE table_name MODIFY SETTING readonly = 1; ``` 此设置会阻止对执行任何写入操作(如 `INSERT`、`DELETE`、`ALTER TABLE ... ADD COLUMN` 等),但允许执行查询操作。需要注意的是,该设置在重新加载(重启服务或重新加载)后仍然有效[^1]。 ### 方法二:通过文件系统权限控制 对于使用本地存储引擎(如 `MergeTree`)的ClickHouse 将数据存储在文件系统中。可以手动更改数据目录的权限,使其不可写。例如,在 Linux 系统中,可以使用以下命令: ```bash chmod -w /var/lib/clickhouse/data/database_name/table_name ``` 这种方式会直接限制操作系统层面对该数据目录的写入权限,适用于需要长期保持只读状态。需要注意的是,这会影响所有尝试写入该的操作,包括后台合并等操作,可能导致服务异常[^1]。 ### 方法三:使用用户权限管理 通过设置用户权限来限制对特定的写入操作。可以使用以下语句限制某个用户对的写入权限: ```sql REVOKE INSERT, ALTER ON database_name.table_name FROM user_name; ``` 此方法适用于多用户环境,允许管理员灵活控制不同用户的访问权限,而无需修改本身的设置或文件系统权限。需要注意的是,该权限控制仅适用于通过 SQL 接口进行的操作,无法阻止通过文件系统直接修改数据的情况[^1]。 ### 方法四:使用视图替代原始 如果主要用于查询操作,可以考虑将原始设置为只读,并创建一个视图供用户查询。例如: ```sql CREATE VIEW view_name AS SELECT * FROM original_table; ``` 然后,将用户访问权限授予视图而非原始。这种方法可以有效隔离写入操作,同时保持查询灵活性。需要注意的是,视图本身不存储数据,因此不会影响原始的性能或存储结构。 ### 方法五:使用 `ATTACH` 命令重新加载只读 如果希望将某个在加载时即为只读状态,可以在配置文件中定义该只读,或在运行时使用 `ATTACH` 命令加载时指定只读标志。例如: ```sql ATTACH TABLE table_name READONLY; ``` 此方法适用于需要在加载阶段即限制写入的场景,确保在整个生命周期内保持只读状态。需要注意的是,该设置在重新加载后仍然有效。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jacky_wxl(微信同号)

喜欢作者

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值