get database write lock timeout问题处理手册

get database write lock timeout问题处理手册

背景

使用 starrocks 过程中我们偶尔会遇到 ‘get database write lock timeout’ 类似的报错,通常是因为库级别有很多的写入任务引起的。下面我们简单说下如果使用过程中遇到此类问题该如何处理。

问题分析

这是由于历史的设计原因,我们在访问 starrocks 的元数据时,通过持有一把 DB 级的大锁来保证元数据读写访问的一致性,这个方式的优缺点都很明显。优点是实现简单,正确性也有保障,缺点是锁的粒度太粗,会导致无关的操作产生锁竞争(lock contention),降低执行效率,后续版本我们会优化此类锁问题,尽量避免粗粒度的锁占用太多资源

解决方式

  1. 将库级别的导入频次降低。减少单位时间的写入次数。

针对不同的导入方式分别调整导入间隔,降低写入频次,具体load参数参考

导入问题 too many tablet version解决方法

避免使用jdbc insert数据或者insert into values方式写入数据,使用微批导入的数据的方式,单表建议写入间隔5s+(1 并发 )

  1. 库中表数量很多的时拆分为多个库

由于锁是DB级别的,因此当DB级别锁竞争比较大时,常见于库有很多表(比如上千表)且均有不低的写入频次时,可以考虑将表分库,也能缓解此类问题

  1. 可使用工具批量导出建表语句

使用说明

python olapdump.py [--host HOST] [--port PORT] [--user USER] [--password PASSWORD] [--database DATABASE]
example: python olapdump.py -h 127.0.0.1 -P 9030 -u root -d dtest > dump.sql
  1. 新建库表,并迁移数据
## 新建database
create database newdata
## 新建table 具体迁移表建表语句采用上述工具dump的sql
CREATE TABLE `test` (
  `k1` int(11) NULL COMMENT "",
  `k2` varchar(20) NULL COMMENT ""
) ENGINE=OLAP 
DUPLICATE KEY(`k1`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`k1`) BUCKETS 20 
PROPERTIES (
"replication_num" = "3",
"in_memory" = "false",
"storage_format" = "DEFAULT",
"enable_persistent_index" = "false"
);
## 将原表数据写入新表
insert into newdata.test select * from data.test
  1. 修改导入任务中的表名

离线例行任务可以将导入任务中的表名 data.test 替换为 newdata.test 并重启任务。

实时任务需要在迁移数据前暂停任务,迁移写入完成后,从上次的消费点往新表去写,下面以routine load为例:

  1. PAUSE ROUTINE LOAD FOR test1; 暂停routine load作业

  2. SHOW ROUTINE LOAD FOR test1;查看并记录当前消费的offset,如下有4个partitions{0,1,2,3}

“0”:4492297965表示partition 0消费进度为4492297965

DataSourceProperties: {"0":4492297965,"1":2633828643,"2":4492269032,"3":2633828635}
  1. 新建任务并继续之前的消费进度

新建任务在from kafka中指定消费的offset,需要注意的是,任务记录offset值是消费到的数据,新建一个任务继续消费的话指定的offset需要手动加1,否则会出现部分数据重复消费的情况。如pause时消费进度为"0":4492297965,则重新消费需要从4492297966开始消费,示例如下

FROM KAFKA
("kafka_broker_list" = "broker1:9092,broker2:9092,broker3:9092",
"kafka_topic" = "my_topic",
"kafka_partitions" = "0,1,2,3",
"kafka_offsets" = "4492297966,2633828644,4492269033,2633828636");
  1. 确认新建任务消费正常后,将之前旧表的消费任务stop即可
1赞

大佬,这个问题在新版本里面优化了吗?

这个改动比较多,还没优化。

排查方向

  1. DDL操作,如建表分区分桶比较多;truncate table等

  2. 库表比较多,导入任务频繁

  3. 是否开启pipeline,并行度高

show global variables like ‘%pipeline%’;

show global variables like ‘%parallel_fragment_exec_instance_num%’;

你好,目前我们从2.5.4版本升到3.0.5后升到3.1.2版本,业务变化不大,但是却频繁的出现get database write lock timeout锁库问题。可以进行交流一下吗?我在社区群4-王磊

这一块导入任务频率大概是多少就是较高的水平呢?
pipeline的开启是否会有较大的影响呢?https://cdn-forum.starrocks.com/original/2X/7/752cfd86d52d352b26ff65a04b47ec751f70b3fc.png

当前集群节点个数以及机器配置是多少,导入任务中是否存在较多的 insert into select 复杂计算,是否开启资源组

3fe + 20be CPU:2路2 * 20核 内存:512G DDR4 磁盘:4 * 1920G(固态)盘
导入任务中是否存在较多的 insert into select 复杂计算不是很多,
资源组有开启

可以提供一台be.INFO日志看下么?还有fe leader的fe.log日志

我们也是这个,从2.5.13 直接升上来 ,会锁库,大佬你是怎么解决的,除了重启fe ,还有别的方案吗

如果导入任务中是否存在较多的 insert into select 复杂计算 会有什么问题吗

如果truncate table比较多会有什么影响

truncate 底层会创建删除的数据对应的空的tabelt,同时进行较多的truncate操作时,会创建很多tabelt,可能会占用锁时间较长,出现lock 相关问题。