GKE环境下旧Pod删除后新Pod无法获取Liquibase锁,修改锁表无效如何解决
GKE环境Liquibase锁无法释放问题排查修复方案
第一步:校验锁表修改是否实际生效
你执行的锁释放SQL本身是官方默认方案,失效优先排查以下问题:
- 确认操作的数据库是否匹配:GKE多环境场景下常出现连接配置混淆,操作了其他环境的数据库,需核对应用Pod内的数据库连接配置和你执行SQL的数据库是否一致
- 确认事务已提交:如果使用未开启自动提交的数据库客户端执行SQL,
update操作未提交不会实际生效,执行完更新后要执行commit命令 - 确认锁表的行ID是否为默认值:执行查询语句查看锁表全量数据,确认实际持有锁的行ID:
部分自定义配置的Liquibase锁行ID不是默认值1,需替换为查询到的实际ID执行更新select * from DATABASECHANGELOGLOCK;
第二步:排查Pod侧异常
- 确认持有锁的旧Pod已完全销毁:执行
kubectl get pods -n <你的命名空间>,确认报错中提到的Podmain-78ddd4b475-t8c68已完全终止,无残留进程占用数据库连接持有锁 - 确认应用未同时启动多副本:多副本部署场景下,你刚释放锁就会被其他启动中的Pod抢锁,新Pod始终拿不到锁。此时需要先把应用副本数调整为1,等Liquibase变更执行完成、Pod启动成功后再调整回原副本数
- 确认Liquibase表配置未自定义:如果应用配置了
liquibase.liquibase-schema(指定锁表所在schema)、liquibase.table-prefix(锁表前缀)参数,你操作的默认DATABASECHANGELOGLOCK表并不是应用实际使用的表,需调整SQL操作对应schema/前缀的锁表
第三步:标准修复流程
注意:不要轻易删除DATABASECHANGELOG表的记录,该表存储变更历史,删除后会导致已执行的SQL变更重复执行,引发表已存在、主键冲突等更严重的问题
按照以下流程操作即可解决:
- 将关联该数据库的所有应用副本数调整为0,确保没有任何进程连接数据库占用锁:
kubectl scale deployment <你的部署名> -n <你的命名空间> --replicas=0 - 登录对应业务数据库,执行以下SQL:
-- 确认锁状态 select * from DATABASECHANGELOGLOCK; -- 释放锁,将id替换为上一步查询到的实际锁行ID,默认是1 update DATABASECHANGELOGLOCK set locked=0, lockgranted=null, lockedby=null where id=1; -- 提交事务 commit; -- 再次查询确认locked字段已变为0,锁已释放 select * from DATABASECHANGELOGLOCK; - 先将应用副本数调整为1,启动单个Pod:
kubectl scale deployment <你的部署名> -n <你的命名空间> --replicas=1 - 确认Pod启动成功、Liquibase变更执行完成后,再将副本数调整为原来的正常值
内容的提问来源于stack exchange,提问作者StackOverflow Asker
相关产品推荐
相关产品推荐

