第六章 逻辑结构管理
6.9 索引
6.9.2 索引的分类
PostgreSQL支持以下几类索引:
- B-tree:最常用,适合处理等值查询和范围查询;
- Hash:只能处理简单等值查询;
- Gist:可用于图形操作符;
- SP-GiST:空间分区GiST索引;
- GIN:反转索引
6.9.3 创建索引
CREATE INDEX indexname on tablename(column_name)
6.9.4 并发创建索引
CREATE INDEX CONCURRENTLY indexname on tablename(column_name)
6.9.5 修改索引
ALTER INDEX name RENAME TO new_name;
ALTER INDEX name SET tablespace_name;
6.9.6 删除索引
DROP INDEX indexname;
6.11 事务、并发、锁
6.11.1 ACID
略
注意区别不可重复读和幻读。
PostgreSQL中,可以使用多版本并发控制(MVCC)来维护数据一致性。
6.11.2 DDL事务
PostgreSQL与MySQL最大区别:大多数DDL可以包含在一个事务中,也可以回滚。
具体场景:多个节点建相同的表(分库分表),将这些建表语句放在同一个事务中。
6.11.3 事务的使用
-
将AUTOCOMMIT设置为off
# \set AUTOCOMMIT off # \ehco : AUTOCOMMIT off
-
使用“BEGIN”语句来启动一个事务
# begin; BEGIN ... # rollback; ROLLBACK
6.11.4 SAVEPOINT
PostgreSQL支持保存点,用以回滚至整个事务的某一个点。
# begin;
BEGIN
...
# savepoint my_savepoint01
...
# rollback to SAVEPOINT my_savepoint01;
ROLLBACK
6.11.5 事务隔离级别
数据库四个隔离级别:
-
READ UNCOMMITTED:读未提交
-
READ COMMITTED:读已提交(PostgreSQL默认隔离级别)
-
REPEATABLE READ:重复读(MySQL默认隔离级别)
-
SERIALIZABLE:串行化
6.11.6 两阶段提交
两阶段提交是实现分布式事务的关键。
两阶段提交协议五个步骤:
- 应用调用各数据库执行各自操作,不提交;然后应用调用事务协调器中的提交方法;
- 事务协调器通知各数据库,准备提交事务,第一阶段开始。PostgreSQL一般是调用“PREPARE TRANSACTION”;
- 各数据库收到命令,返回成功(或失败);数据库需确保后续在被要求提交事务时能够提交事务,或被要求回滚时能够回滚。PostgreSQL会将已准备好提交的信息写入持久存储区中。若数据库无法完成此事务,则返回失败给事务协调器;
- 事务协调器收到所有数据库的响应;
- 在第二阶段,如果有任意一个数据库返回了失败,则事务协调器会发送一个回滚命令(ROLLBACK PREPARED)给各数据库。如果所有返回都为成功,则发送“COMMIT PREPAREED”命令,通知各数据库事务成功。
其中第二个步骤,PREPARE TRANSACTION transcationId,transcationId为全局事务ID,由事务协调器生成。PostgreSQL一旦成功执行这条命令,就会把此事务持久化,及时数据库重启,此事务既不会回滚,也不会丢失。
6.11.7 锁机制
表级锁、行级锁
SHARE 共享锁(读锁)、EXCLUSIVE 排它锁(写锁)
多版本功能下,表锁增加ACCESS SHARE和ACCESS EXCLUSION
意向锁:ROW SHARE、ROW EXCLUSIVE
6.11.8 死锁及防范
死锁四个必要条件:
- 互斥;
- 请求和保持条件(占有并等待);
- 不可抢占;
- 环路等待条件(循环等待)
死锁防止方法:以固定顺序获取对象的锁(事务中以固定顺序更新数据表)
第七章 PostgreSQL核心架构
进程及内存结构
-
Postmaster主进程
Postmaster是整个数据库实例的总控进程。
PostgreSQL数据库是进程架构模型,MySQL数据库是线程架构模型
-
SysLogger(系统日志)进程
配置文件postgresql.conf中参数:logging_collect为“on”时,主进程才会启动SysLogger辅助进程;
收集所有stderr输出,并写入到日志文件中。
-
BgWrite(后台写)进程
功能:将共享内存中脏页写到磁盘上(脏页刷盘);
作用:提高增删改的效率;
类比:操作系统页缓存机制。
-
WalWriter(预写式日志写)进程
功能:修改数据之前,先记录修改操作至磁盘,再实际更新数据;
作用:宕机后重启也可以根据WAL日志重新执行,以恢复宕机前状态;
WAL日志保存在pg_xlog下,每个pg_xlog文件默认为16M;
类比:类似于Redis的AOF,但Redis是先执行命令,再记录至AOF。
-
PgArch(归档)进程
功能:将WAL日志文件再覆盖前备份出来;
目的:解决WAL日志循环使用覆盖问题;
数据库全量备份后,将备份时间点之后的WAL日志通过归档进行备份。全量备份加后续产生的WAL,即可恢复至全量备份后任意一时间点的状态。
-
AutoVacuum(自动清理)进程
PG中,删除数据不会立马被删除,更新数据不会在旧数据上操作,而是生成一行新数据(MV);
旧数据只是被标识为删除状态,只有并发的其他事务读到这些旧数据时,它们才会被清除。清除工作由AutoVacuum进程完成。
-
PgStat(统计数据收集)进程
共享内存
-
共享内存主要用作数据块缓冲区,以提高读写性能。
-
WAL日志缓冲区和CLOG(Commit log)缓冲区也在共享内存中、还有其他一些全局信息。
-
PostgreSQL9.3之后,使用“mmap()”方式实现共享内存。
本地内存
存储一些不需要全局存储的数据,主要有:
- 临时缓冲区:用户访问临时表的本地缓冲区;
- work_mem:内部排序操作和Hash表在使用临时磁盘文件之前使用的内存缓冲区;
- maintenance_work_mem:在维护性操作中使用的内存缓冲区。