mac可以通过命令行用brew来安装或者直接下载安装包来安装,网上资料很多,这里就不介绍了。
如果通过brew来安装的,可以通过brew services start/stop postgres来开启或停止。
还有一种方法是通过docker来跑,这里以mac桌面版为例,创建启动脚本pg-docker-compose.yml:
# Use postgres/example user/password credentials
version: '3.1'
services:
pgsql:
image: postgres:12
restart: always
privileged: true
ports:
- '5432:5432'
environment:
POSTGRES_USER: 'postgres'
POSTGRES_DB: 'postgres'
POSTGRES_PASSWORD: 'postgres'
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- /Users/xxx/docker/postgres/data:/var/lib/postgresql/data/pgdata
通过 docker-compose -f pg-docker-compose.yml up -d
启动docker。打开就能看到容器已经启动了,如下所示:
接下来可以通过pgAdmin来进行数据库访问和操作。具体安装过程这里不介绍。
安装完成之后,创建数据库连接,以上面的docker启动的数据库为例,连接参数如下:
postgres与mysql有点不一样,mysql的table是database的下级元素,而postgres的database下面还有schemas,其中public是默认的schema,schema下面才是table。
在需要操作的表格上右键,选择不同的script,可以进行数据操作。其中,PSQL Tool是客户端命令行(如果安装了postgres服务端而没有安装pgAdmin,可以直接通过psql来开启命令行)。
postgres常用命令:
操作 | 含义 |
---|---|
\l | 列出所有databases |
\c | 当前用户和连接的表 |
\c databaseName | 切换数据库 |
\c - username | 切换用户 |
\dn | 查看数据库中所有schemas |
\du | 查看数据库中所有role及其权限 |
\dt | 查看数据库中所有表 |
\d tableName | 查看某个表的描述 |
\d+ tableName | 查看某个表的基本信息 |
\di | 查看索引 |
\df | 查看存储过程 |
\encoding | 查看编码 |
点开Login/FGroup ROles
可以查看role和其属性,包括每个role的权限,如下所示:
可以看出,postgres是一个super用户,拥有所有权限。
查看当前登录用户并创建一个新用户:
可以看到新用户test只有login权限。
注意关键字role和user的区别,如create user会自动赋予用户登录权限,而create role不会。
切换到test用户(注意必须与登录用户的密码相同才能切换,否则要修改db连接密码重新登录),然后创建新用户:
此时会发现无法创建新的role,因为当前登录用户test不具有创建role的权限。
重新切换回super用户,修改test用户的权限:
然后切换到test用户就可以创建新角色了:
切换到新用户test1,尝试删除本身:
因为test1只有login权限,所以不能删除role。可以切换到具有createrole权限的test用户来删除:
如果当前用户拥有删除role权限但报错:
cannot be dropped because some objects depend on it
说明这个不能删除的role拥有其他对象。但是drop role并没有cascade删除指令,只能先删除其拥有的其他对象,再删除role:
drop owned by xx cascade;
drop user xxx
注意:执行此操作需保证要删除的role所拥有的其他objects确实是可以删除的。
test用户虽然具有创建role和db的权限,但是不能创建public模式。将postgres的权限赋予test,然后查看用户权限信息:
此时可以看到:test是postgres的一个成员,因此具有创建public模式的权限:
如果执行某项操作报错:
ERROR: must be member of role "xx"
则同样地,将xx权限赋予给当前用户:
grant xx to current_user
这样当前用户就成为xx的成员,可以将当前用户所拥有的一些table或者schema转让给xx。
查询所有表的记录数
select schemaname, relname, n_live_tup from pg_stat_user_tables order by n_live_tup desc;
可以使用以下命令进行数据dump:
pg_dump -Fc -v -b -h localhost -p 5432 -U postgres -E UTF8 -d postgres > test.dump
生成原始数据的校验文件:
psql -hlocalhost -Upostgres -p5432 -d postgres -f test.sql > validation_test.txt
校验脚本如下:
create function validation() returns text
language plpgsql as $$
DECLARE
rec record;
countTable bigint;
sumRowHashTable bigint;
sch record;
seqName record;
seq record;
results text;
BEGIN
results = '';
-- table hash
FOR sch IN
SELECT *
FROM information_schema.schemata
WHERE schema_name <> 'pg_catalog' and schema_name <> 'information_schema'
ORDER BY schema_name
LOOP
FOR rec IN
SELECT *
FROM pg_tables
WHERE schemaname = sch.schema_name
ORDER BY tablename
LOOP
EXECUTE 'SELECT count(*) FROM '
|| quote_ident(rec.schemaname) || '.'
|| quote_ident(rec.tablename)
INTO countTable;
-- adjust for precision of datatype for diffrent postgres version, this is for example
IF rec.tablename = 'order' THEN
EXECUTE 'SELECT sum(CAST(CAST((''x'' || md5(CAST((f.id, round(f.amount::numeric, 6), f.createTime) AS text))) AS bit(32)) AS int)) FROM '
|| quote_ident(rec.schemaname) || '.'
|| quote_ident(rec.tablename) || ' f'
INTO sumRowHashTable;
ELSE
EXECUTE 'SELECT sum(CAST(CAST((''x'' || md5(CAST((f.*)AS text))) AS bit(32)) AS int)) FROM '
|| quote_ident(rec.schemaname) || '.'
|| quote_ident(rec.tablename) || ' f'
INTO sumRowHashTable;
END IF;
IF results = '' THEN
results = rec.schemaname || '.' || rec.tablename || ',' || countTable || ',' || sumRowHashTable;
ELSE
results = concat(results, CHR(10), rec.schemaname || '.' || rec.tablename || ',' || countTable || ',' || sumRowHashTable);
END IF;
END LOOP;
END LOOP ;
-- sequence
results = concat(results, CHR(10), CHR(10), CHR(10), CHR(10), CHR(10), '-------------------------------------');
FOR seqName IN
SELECT c.relname
FROM pg_class c
WHERE c.relkind = 'S'
ORDER BY c.relname
LOOP
-- change 'public' to your own database schema
EXECUTE 'SELECT * FROM ' || 'public' || '.' || quote_ident(seqName.relname)
INTO seq;
results = concat(results, CHR(10), seqName.relname || ',' || seq.last_value || ',' || seq.log_cnt || ',' || seq.is_called);
END LOOP ;
RETURN results;
END;
$$;
select validation();
DROP FUNCTION validation();
接下来通过以下命令进行数据恢复:
pg_restore -Fc -v -h localhost -p 5432 -U postgres -d postgres test.dump
恢复之后,同样用相同的脚本生成校验文件,比较校验文件是否相同。