前言

欢迎来到我的Debug系列第一集,我目前还没有完全想好这个系列该怎么去组织规划,但是我想记录下来遇到的大大小小的bug以及debug的过程应该于我自己而言是一件蛮有意思的事情。

即使人们常说我们所遇到的bug别人一定都遇到过,去Google一定都能解决,但是如果遇到相同bug的人并没有发表于网络呢?那我们可能真的搜索不到这个bug。并且每个人的操作环境总会有大大小小的差异,所以我还是认为每个人的每个bug都是独一无二的,要说搜索解决方法,不如说是去搜索类似的问题来启发自己。

所以,让我们来记录这一切,万一哪天能启发到别人呢?让自己感受文字的温暖吧。

Postgresql的连接问题

问题背景

我在启动一个新的项目时,使用docker启动Postgresql,使用了下方这样一个docker命令写在了我的Makefile中。

lanch_postgres:
	docker run --name postgres_urls \
	-e POSTGRES_USER=LTX \
	-e POSTGRES_PASSWORD=Lutaol123 \
	-e POSTGRES_DB=urldb \
	-p 5432:5432 \
	-d postgres

命令的含义是运行一个名为postgres_urls的容器,特权用户为LTX(这里直接使用特权用户操作数据库了),密码为Lutaol123,数据库名称为urldb,端口映射主机的5432映射到容器中的5432端口,-d使容器在后台持续运行——以postgres这个镜像为基础的容器。

执行make lanch_postgres后成功启动了这个容器,接着来到数据库迁移(使数据库操作变得可以回滚,变得像Git一样的可以进行版本控制)具体如何迁移见官方链接最终效果就是在容器中的数据库执行了一条建表的语句

这一阶段的makefile如下:

databaseURL="postgres://LTX:password@localhost:5432/urldb?sslmode=disable"

migrate_up:
	migrate -path="./database/migrate" -database=${databaseURL} up

可是执行makefile,make migrate_up时报错:

postgres://LTX:Lutaol123@localhost:5432/urldb?sslmode=disable
migrate -path="./database/migrate" -database=postgres://LTX:Lutaol123@localhost:5432/urldb?sslmode=disable up
error: failed to open database, "postgres://LTX:Lutaol123@localhost:5432/urldb?sslmode=disable": pq: role "LTX" does not exist
make: *** [migrate_up] Error 1

问题处理过程

错误信息

错误信息是打开数据库失败,“LTX"这个用户不存在。

经检查可以发现path是没有问题的,意味着我们写的数据库连接URL是正确的。而最后的pq: role "LTX" does not exist才是真正的问题所在。

但是上面我们使用docker创建这个Postgresql容器时不是成功了吗?这里怎么又不存在了呢?

尝试解决

  1. 检查makefile中的命令有无错误
  • 通过错误信息可以得知,我们的路径信息都是正确的,即迁移命令和docker命令中的信息是吻合的。
  • 所以一定不是这里的问题。
  1. 检查Docker容器
  • 这里我们取巧,直接去Dockerdesktop桌面化环境中去检查,打开指定的容器后,输入命令psql -U LTX -d urldb进入到数据库中,发现进入成功了?那用户怎么会不存在呢?
  • 再执行一系列的Postgresq命令检查当前连接信息\conninfo显示正常连接, 检查数据库信息\l显示所有的数据库发现存在urldb;
  • 但是查询数据库中的所有表信息时出现了错误,\dt显示并没有表?

所以,很明显迁移命令没有执行成功,因为表都没有。

看到这里你也许会有疑惑,为什么数据库创建好了呢?

  • 这和最初的docker命令有关,指定了POSTGRES_DB和POSTGRES_USER之后容器启动时会自动创建我们所指定的数据库和超级用户
  • 可以使用\du命令检查用户权限

最终解决

那到底为什么没有连接成功呢?我突然一想,自己之前做过一个项目也是使用的Postgres,并且我是在本地使用的,不会这个迁移命令给我连接到了本地了吧?!

# 进入本地的数据库
psql postgres
# 检查当前数据库信息
\l

坏啦!怎么本地数据库里面有urldb这个数据库啊!那一定是连接到本地了(因为我之前并没有操作本地Postgres)。再连接这个数据库查查表信息确认一下。

# 连接urldb数据库并检查表信息
\c urldb
\dt

这里Owner变成了ltx_urldb是因为后来我改了一次用户名(因为当初我还以为是用户名的问题)

哦豁,真的是迁移到本地的Postgresql中了,并没有去连容器中的。

错误原因

那到这里,错误原因也很明显了,就是databaseURL="postgres://LTX:password@localhost:5432/urldb?sslmode=disable"这个数据库链接指向的是localhost,如果本地的运行着,自然就连接到本地了。

这里做个回调小实验,将本地的关闭然后再次尝试向容器中迁移。

# 因为我是用homebrew安装的
brew services stop postgresql

再次执行迁移命令发现成功了

进入容器中也查到了相应的表。

总结

一个localhost引发的本地数据库和容器数据库之间的冲突。

其中更底层的原因我询问了GPT:

  • PostgreSQL 默认在 /var/run/postgresql/.s.PGSQL. 路径监听 Unix 套接字,如果 PostgreSQL 客户端检测到本地套接字文件,就会优先通过它连接。
  • 如果本地套接字不可用,则尝试通过 localhost:5432 使用 TCP/IP 连接。并使用端口映射到容器中的5432端口。

好的到这里我们的这次Postgresql的容器连接问题就到这里结束了。

这里是LTX,感谢您阅读这篇博客,人生海海,和自己对话,像只蝴蝶纵横四海。