aclyyx's Blog

aclyyx's Blog

记录一次瀚高数据库使用过程中莫名其妙的行锁事件

2025-04-10
记录一次瀚高数据库使用过程中莫名其妙的行锁事件

事后总结发现可能是在创建表是写错了自动生成ID的cache的数据导致锁表的发生。

事件描述

写了一句简单的将select的结果通过insert插入表中的SQL语句,在执行后莫名其妙的卡住,一直无法返回执行结果。同样功能的其他语句则毫无问题。

解除锁

网上通篇是通过查询锁语句找到被锁的表,再找到导致锁表的进程,通过进程号解除锁

select * from pg_locks a
join pg_class b on a.relation = b.oid
join pg_stat_activity c on a.pid = c.pid
where a.mode like '%ExclusiveLock%';

select pg_cancel_backend(a.pid) from pg_locks a
join pg_class b on a.relation = b.oid
join pg_stat_activity c on a.pid = c.pid
where b.relname ilike 'prefab_project_completed' 
and a.mode like '%ExclusiveLock%';

--或者使用更加霸道的pg_terminate_backend():
select pg_terminate_backend(a.pid) from pg_locks a
join pg_class b on a.relation = b.oid
join pg_stat_activity c on a.pid = c.pid
where b.relname ilike 'prefab_project_completed' 
and a.mode like '%ExclusiveLock%';
  • 解除锁的方法:
select pg_cancel_backend(pid);
select pg_terminate_backend(pid);

但结果不尽如人意,锁的很死,也极为顽强。

重启数据库服务

通过停止再启动服务器,试一下什么效果。

# 由于启动瀚高服务时指定了数据目录,所以在停服务时也需要添加相应的参数
pg_ctl stop -D /data0/highgo/data

执行命令后,等了许久但最终还是显示服务停止失败,反复数次后才发现,这时数据库服务已经无法访问了,可通过ps -ef|grep hgdb命令查看数据库服务的进程还在。

最终使用 kill -9 pid 强杀了服务进程。

这时,通过 ps -ef|grep postgres 仍能看到之前执行被锁的 insert sql 进程。

通过启动服务命令启动瀚高数据库服务,提示缓存空间被占用,导致服务无法启动。

# 指定数据目录启动
pg_ctl start -D /data0/highgo/data

通过 ipcs 查询缓存空间

ipcs -m 32778

通过 ipcrm 清除缓存空间

ipcrm -m 32778

服务可以正常启动,且使用管理工具也可以连接到服务。

还是强杀

反复折腾未果,insert sql 进程还在,最后还是用 kill -9 强杀进程。

最终

万幸,在处理后经过验证未对数据库中的数据造成影响。