1. 为什么要在手机上跑 PostgreSQL:先把需求和边界看清楚
1.1 被一张“临时要的报表”逼出来的方案
前阵子出差,笔记本忘在酒店,临时要核对一组客户名单,手边只有手机。虽然手机上有不少现成的数据库 App,但要跑一段跨表关联的 SQL,还真没几个能顺手。于是我想起 Termux——那个看起来像“终端模拟器”的 App,其实把包管理器、编译工具链全给你备齐了,可以原地装一个 PostgreSQL 数据库,在手机上直接跑 SQL。我花了一个晚上把流程跑通,后来又断断续续用了一个多月,这条路完全能走通。
这篇文章记录我从零开始在 Termux 上安装、配置 PostgreSQL 的完整过程。你不一定能用它替代正式的数据库服务器,但在出差、通勤、演示这种“手边没有电脑”的场景里,它确实能救急。适合的读者大概是这样几类:经常临时查数据的开发、想在手机上学 PostgreSQL 命令的新手、需要在移动环境里搭一个演示数据库的讲师。
如果你只是好奇“手机能不能跑数据库”,那我可以直接告诉你:能,而且比想象中稳。但你得先清楚它适合干什么,否则很容易把它当成“手机替代电脑”的万能方案,用起来才会失望。
1.2 这套方案的边界:能做什么,不能做什么
把预期摆正很重要。手机跑 PG 数据库,本质是在 Android 的 Termux 用户空间里运行一个完整的 PostgreSQL 主进程,组件和工作原理与服务器上完全一致:有后台进程、有数据目录、有 WAL 日志、有网络监听端口。因此,单表查询、多表 JOIN、事务、视图、存储过程这些功能都能正常用。
但它能跑不代表适合所有负载。手机 CPU 弱、内存小、存储是闪存,高频写入既费电也伤盘。所以我的定位是:临时开发环境、学习练习环境、演示环境,以及小数据量的分析工作。生产级高并发、海量数据仓库这类场景,就不要为难手机了。
说白了,手机里的 PG 更像一个“随身携带的 SQL 沙盒”。你把需求想得越轻量,这套方案用起来就越顺手。我后面讲的所有优化,也都是围绕“让它在轻量场景下更稳”展开的,不是为了把它调成一台小型服务器。
1.3 我为什么不直接装一个完整 Linux 发行版
在 Termux 里跑 PostgreSQL 有两条路:第一条是用pkg install postgresql直接装 Termux 原生包;第二条是用proot-distro安装 Ubuntu 或 Debian,再在里面的标准 Linux 环境装 PostgreSQL。两条路我都试过,下面这个对比能帮你少走点弯路:
| 对比项 | 原生包方案 | proot 发行版方案 |
|---|---|---|
| 安装体积 | 小,几十 MB 级 | 大,发行版根文件系统至少一两个 GB |
| 启动速度 | 快,秒级拉起 | 慢,proot 解析过程有额外开销 |
| 兼容性 | 与 Termux 打包体系深度集成 | 更接近标准 Linux 文件系统结构 |
| 常用路径 | 使用$PREFIX下的路径 | 使用/usr/bin、/var/lib等标准路径 |
| 适合场景 | 轻量开发、临时查询 | 需要特定发行版软件包的环境 |
我最终日常用的是原生包。原因很简单:应对“临时查数据”这种需求,原生包装完就能跑,不用为文件系统层级和依赖兼容问题多操心。如果你需要练手环境越接近服务器越好,proot 方案也不是不行,但下面的步骤全部以原生包方案为准,这也是 Termux 社区里操作成本最低的路线。
2. 动手前的环境准备:Termux 需要先过这几关
2.1 安装渠道与基础包更新
Termux 官方推荐的安装渠道是 F-Droid,应用商店里也有其他渠道,但版本不一定同步。安装完成后第一件事是更新基础环境:
pkg update pkg upgradepkg是 Termux 封装的包管理命令,底层基于 APT,但做了很多针对 Android 的调整,不需要 root 权限。第一次执行 upgrade 时可能会下载不少基础库,耗时取决于网络和手机性能,十几分钟到半小时不等。如果中间出错,先pkg update再重新pkg upgrade,多数情况能恢复。
这里插一句:很多刚接触 Termux 的人会急着装软件,结果核心依赖都没更新,后面各种“语义奇怪”的报错都会冒出来。我个人的习惯是连续执行两次pkg update && pkg upgrade,确认没有包需要更新后再往下一步。尤其是隔了一段时间重新打开 Termux 时,先更新再运行已有程序,能避免不少兼容问题。
2.2 存储和权限:为什么总有人连数据目录都起不来
Termux 默认运行在自己的私有数据目录里,也就是 Android 分配给应用的空间,对外表现为$PREFIX。新版本内部一般会自动初始化,不需要手动建目录。但如果你希望通过文件管理器访问 Termux 内部文件,需要先执行termux-setup-storage申请存储权限,把/sdcard等目录映射到 Termux 内。
对 PostgreSQL 来说,更关键的是确认$PREFIX所在分区有足够空间。先执行:
df -h $PREFIX如果发现可用空间不足 1 GB,建议先清理$PREFIX/var/cache下的缓存包,再用pkg clean清一遍。别小看这一步,有些人数据库初始化失败,并不是配置问题,而是数据目录所在空间已经满了。
另外提醒一下,Termux 的pkg安装包默认不需要 root,PostgreSQL 同样如此。反过来讲,如果你在一个已经 root 过的环境下强行用 root 权限初始化数据目录,反而容易把属主关系搞乱,后面启动服务时报权限错误,排查起来很麻烦。
2.3 让服务在手机锁屏后还能活着的准备
手机的省电策略是 Termux 无法绕过的。默认情况下,屏幕熄灭一段时间后,Android 会冻结后台应用,PostgreSQL 表现为 SQL 连接超时或服务直接无响应。要提前做准备:
pkg install termux-api然后执行termux-wake-lock申请唤醒锁。它相当于告诉系统“这个应用有持续任务,不要轻易冻住我”。如果之后要释放锁,执行termux-wake-unlock即可。
同时建议在系统设置里把 Termux 加入“电池优化白名单”或“后台运行不受限”列表。注意,这个设置入口的名字每个品牌都不一样,一般都在“电池 / 应用启动”附近,需要自己找一下。准备工作做到这里就差不多了。每条我在手机上反复跑过,顺序打乱或跳过某个步骤时,后面多半会踩到莫名其妙的坑。
3. 原生包安装 PostgreSQL:从 pkg 到 initdb 的完整流程
3.1 安装并确认版本
执行:
pkg install postgresql安装完成后确认版本:
psql --version正常情况下会显示 PostgreSQL 的版本号,我这边演示的是 16 主版本。Termux 的包维护商会跟随上游版本,具体是 15 还是 16,以你安装时的软件源为准。版本号很重要,因为后面升级大版本时旧数据目录无法直接使用,这一点我在第 5 节会专门讲。
安装包只提供可执行程序,数据库的数据目录还需要你手动初始化。这和 Linux 发行版大多会在安装脚本里自动做完初始化不太一样,也是不少新手卡住的第一道坎。先别急着启动服务,按顺序往下走就行。
3.2 初始化数据目录:理解 initdb 到底做了什么
PostgreSQL 的数据目录会存放配置、数据库文件、WAL 日志等所有持久化内容,它不会凭空出现,需要执行初始化:
mkdir -p $PREFIX/var/lib/postgresql initdb -D $PREFIX/var/lib/postgresqlinitdb会生成一个完整的数据库系统:template0、template1、postgres 三个初始库,以及 postgresql.conf、pg_hba.conf 等配置。执行成功后终端末尾会提示 “You can now start the database server”,看到这句基本就成了一半。
这里有一个不少人没想明白的点:initdb执行时用的系统用户就是当前 Termux 用户,初始超级用户名也因此是当前用户的whoami输出,而不是 Linux 服务器上常见的postgres用户。所以用psql -U postgres登录反而会报错的,别照搬网上教程盲目加-U postgres。
初始化过程很快,一两秒就能完成。如果遇到“could not create directory”这类报错,基本就是父目录不存在或权限不够,先mkdir -p再重新执行即可。确认数据目录对当前用户可写,是最稳的起步。
3.3 启动服务与本地连接:先跑通再谈折腾
初始化完成后启动:
pg_ctl -D $PREFIX/var/lib/postgresql start然后直接连数据库:
psql -d postgres这里走的是 Unix 域套接字,不需要输入密码,因为默认pg_hba.conf对本地连接通常是 trust 信任模式。能进入postgres=#提示符,说明 PostgreSQL 主进程已经在手机里正常跑起来了。退出用\q。
停止服务和检查状态的对称操作:
pg_ctl -D $PREFIX/var/lib/postgresql stop pg_ctl -D $PREFIX/var/lib/postgresql status启动时常见的报错是“could not fork process”或“Permission denied”,多与数据目录属主、内存不足有关,后面的第 5 节有完整的排查链路。先确保本地能稳定连上,再去折腾网络访问,否则出问题时会很难分清是哪一层的问题。
3.4 建库、建用户和一套能直接用的兜底 SQL
本地能连上之后,先给后续的远程访问做好准备:创建一套业务账号,而不是一直用超级用户裸奔。在 psql 里执行:
CREATE ROLE dev WITH LOGIN PASSWORD 'Dev@2025'; CREATE DATABASE devdb OWNER dev;再建一张演示表:
\c devdb CREATE TABLE IF NOT EXISTS demo ( id serial PRIMARY KEY, note text NOT NULL, created_at timestamptz DEFAULT now() ); INSERT INTO demo (note) VALUES ('hello termux pg'); SELECT * FROM demo;这套操作覆盖了“角色权限、库属主、表结构、写入与查询”整条链路,能用它验证数据库是否真正就绪。很多初学者只走到“能启动服务”就以为结束了,结果后面远程连接时才发现用错了账号密码,白白浪费时间。每一步报错信息都是有用的,先读懂它再继续。
4. 让局域网里的电脑访问手机上的 PostgreSQL
4.1 改两个文件:监听地址与访问规则
默认情况下 PostgreSQL 只监听localhost,也就是只提供手机本机的连接。要让同一 WiFi 下的电脑或其他设备访问,需要改数据目录下的postgresql.conf:
listen_addresses = '0.0.0.0'同时改pg_hba.conf,增加一条允许局域网网段访问的规则:
host all all 192.168.1.0/24 scram-sha-256注意,这里的192.168.1.0/24只是示例,你要按实际网段改写。不要把认证方式写成trust直接放行,否则任何局域网设备都能免密进来。改完文件后必须重启服务:
pg_ctl -D $PREFIX/var/lib/postgresql restart如果少改pg_hba.conf,连接时会出现“no pg_hba.conf entry for host …”的报错;如果只改了hba没改监听地址,报错则是“Connection refused”。两处配置一个都不能漏。
4.2 确认手机 IP 并在电脑端完成连接
在 Termux 里查看手机在局域网内的 IP:
ip addr show wlan0 | grep inet或者直接用ifconfig。拿到类似192.168.1.23的地址后,在电脑上执行:
psql -h 192.168.1.23 -U dev -d devdb输入密码后能连上,说明“手机作为临时数据库服务器”这条路正式打通。如果电脑端提示连不上,通常先看这三点:手机和电脑是不是同一网段、手机有没有被系统限制后台网络、postgresql.conf修改后有没有重启生效。
我再多说一句为什么要在移动场景里强调这一步:在会议室或者客户现场,很多人手头只有一部手机和一台临时借来的笔记本,如果手机能直接作为数据库被对方连接,演示交互数据时就不用担心“这台电脑上没装数据库环境”这种尴尬事。
4.3 跨网络访问:先想清楚再做
公网访问手机数据库比局域网复杂得多,而且手机通常没有固定公网 IP。我的建议是:除非有明确必要,否则别把 PostgreSQL 直接暴露到公网。原因既有安全考虑,也受移动网络的 NAT 限制。
如果确实需要在外部网络访问,比较常见的思路是借助一台有公网地址的服务器做端口转发,并在这条链路上配置足够的认证和加密。不过这种部署要小心的是,暴露出来的端口很容易成为被探测的目标,所以数据库账号密码不要复用任何其他平台密码,同时建议关闭不使用的服务。公网场景的变数太多,这里不展开完整配置,先把局域网方案用熟,很多临时需求其实已经能覆盖。
5. 踩坑实录:按出现频率排序的典型问题与排查思路
5.1could not fork process与权限错乱
这个报错很典型。出现场景通常是关闭 Termux 应用后重新打开,再执行pg_ctl start时报错。根因大概是两类:一是手机内存压力大,fork 不出新进程;二是数据目录里的文件属主因为某种原因被改动。
排查链路建议这样走:先看系统内存占用,执行free -h,如果 available 不足几百 MB,关掉几个后台应用再试;然后检查目录权限,执行ls -ld $PREFIX/var/lib/postgresql,确认所有者为当前用户。
不要一上来就chmod -R 777。这类目录权限放开反而会让 PostgreSQL 拒绝启动,制造新的麻烦。按正常顺序排查,多数问题出在“上一次没正常停库就杀了进程”导致的状态残留。
5.2 手机休眠导致的连接超时
这是“看似正常但就是连不上”的头号元凶。我的测试中,屏幕灭掉几分钟后,从电脑连接就开始超时,而 Termux 界面显示服务还在。原因是 Android 把应用冻结了,网络会话被一起挂起。
解决方案就是前面说的:用termux-wake-lock锁定,再把 Termux 加入电池优化白名单。如果仍然不稳定,可以插上电源,在开发者选项里开启“充电时屏幕常亮”来临时抢救。不过这种方式费电也费屏幕,只适合应急,不适合每天长时间使用。
另外一个容易踩的点是:有些定制系统的“后台限制”非常激进,即使加了白名单,第二天早上还是发现服务断了。这种情况下可以在 Termux 里配合 tmux 保活会话,同时把日志输出到文件,这样能判断服务是什么时候挂的、为什么挂的。
5.3 大版本升级后旧数据目录失效
Termux 执行pkg upgrade后,PostgreSQL 主版本可能从 15 跳到 16。数据文件格式不兼容,服务直接起不来,日志一般会提示“data directory was initialized by a different version”。
我当时处理的方式是备份并重建:
pg_dumpall > /sdcard/pg_backup_$(date +%Y%m%d).sql pkg upgrade mv $PREFIX/var/lib/postgresql $PREFIX/var/lib/postgresql.bak initdb -D $PREFIX/var/lib/postgresql pg_ctl -D $PREFIX/var/lib/postgresql start psql -f /sdcard/pg_backup.sql这套流程执行完,数据恢复与升级前基本一致。特别注意:pg_dumpall必须在升级前完成,跨版本不能直接读旧数据文件,这是我踩得很疼的一个教训。后来我养成了习惯,每次pkg upgrade之前先看一眼有没有 postgresql 相关的包要更新,有就先备份再做。
5.4 内存不足、写入抖动的日常缓解
手机上跑 PG,最普遍的瓶颈是内存。我把配置改成了适合移动设备的保守值:
shared_buffers = 64MB effective_cache_size = 128MB max_connections = 20max_connections调小可以明显减少每个后端进程的内存开销,shared_buffers保持 64MB 对绝大多数轻量查询足够。如果你的手机内存比较大,可以适当调到 128MB,但这些参数每次修改后都要重启才能生效。
写入抖动方面,可以考虑把synchronous_commit设为off。代价是异常断电时可能丢最近几次事务,换来更快的写入体验。手机上我建议宁可让备份兜底,也不要让每个提交都反复同步到存储,这是综合体验差很多的取舍。
6. 性能表现与日常使用经验
6.1 轻量场景下,手机 PG 能拿得出手吗
我拿一张十万行级别的表做过简单测试:单表统计和带索引的等值查询都在百毫秒到一两秒内完成,这个速度用来做演示和临时分析完全够用。但多表 JOIN 加复杂聚合就能明显感觉到 CPU 吃力,所以建议尽量把查询拆小、分批执行。
手机还有一个问题:散热差。长时间高负载会触发 CPU 降频,延迟可能突然变高。所以如果你要做批量数据处理,不如把手机当成“临时验证环境”,最终计算放到电脑或服务器上。用手机跑数据库的最大价值在于“随时随地能验证想法”,而不在于处理量。
6.2 备份恢复的稳妥姿势
手机丢失、系统更新、误删数据都有可能导致数据库一起消失,备份必须习惯化。最简单的方案是定期执行:
pg_dump -U dev -d devdb > /sdcard/devdb_$(date +%Y%m%d).sql恢复时:
psql -U dev -d devdb < /sdcard/devdb.sql如果有权限或对象名冲突,可以在恢复前先确认库是不是空的,或者重建一个干净的库再导入。注意,备份文件里是明文 SQL,可能包含账号密码等敏感信息,别随手发到聊天记录里。
我个人的习惯是每天写一条自动备份脚本,放在 Termux 的启动目录里,配合termux-api的定时能力执行。这里不想把命令写得过于复杂,但你至少要做到“每天手动备份一次”,否则这套方案给你的便利,可能最终会变成数据事故的隐患。
6.3 我的最终建议:用这块“随身数据库”的另一种思路
一个多月用下来,我对这套方案越来越有感觉。手机上跑 PG 数据库,真正舒服的场景不是“替代服务器”,而是“让数据跟着人走”:临时验证一条 SQL、给同事现场展示一个 demo、通勤路上练习数据库操作,它都能胜任。
如果你准备长期使用,建议再加两步:装tmux,把服务进程放在一个独立会话里管理;在 Termux 的启动配置里加入快速启动命令。我用的是:
tmux new -d -s pg pg_ctl -D $PREFIX/var/lib/postgresql start这样即使应用意外关闭,重新打开 Termux 后还能快速查看数据库状态,不用每次重新想怎么启动。
最后一点:数据不要只存在手机上。别问我为什么强调,有一次手机系统自动更新后,Termux 的数据目录差点没保住。从那以后,我每天都会把核心库的 dump 同步到另一台设备上。手机能成为你随时随地的数据库终端,但绝不能成为唯一一份数据的存放地。