PostgreSQL的事务管理与MVCC(十)
PostgreSQL 入门系列博文讲解(B站同步介绍视频:https://space.bilibili.com/282421760)
支持一下,关注一波微信公众号:【 钥道不止 】
1. 隔离级别
默认隔离级别:读已提交(read committed)
#查看事务的隔离级别
show transaction_isolation;
2. 事务控制
- 缺省:autocommit=on
- 默认隐式提交。可以写入begin; … end;
- 提交:commit
- 回滚:rollback
- 保存点:savepoint
#查看是否是自动提交
\echo :AUTOCOMMIT
#会话级别关闭自动提交(小写无效)
\set AUTOCOMMIT off
3. MVCC
- MVCC(Multiversion Concurrency Control)
- 在数据行被删除和修改的时候,会保留原有副本。通过保存数据某个时间点的快照(snapshot)并控制元组的可见性来实现(事务id大小比较)
- 旧的数据副本由vacuum来做垃圾清理
3.1. 两大功能
- 读不阻塞写,写不阻塞读
- 提供一致性读写
3.2. 事务号
- Transaction id(txid)
- 每当事务开始时,事务管理器都会分配一个唯一的标识符,称为事务ID(TXID)。
- PG的txid是一个32位无符号整数,2^32。 同一个数据库中,存在的最旧和最新两个事务之间的年龄允许的最多是2^31,即20亿。
txid到最大值,又会从最小值 3 开始
* 0:InvalidXID,无效事务ID
* 1:BootstrapXID,表示系统表初使化时的事务ID,最旧
* 2:FrozenXID,冻结的事务ID,比任务普通的事务ID都旧 - 事务启动后会执行内置txid_current()函数,该函数将返回当前txid。
# 查询当前事务号
select txid_current();
# 查询当前事物快照
select txid_current_snapshot();
3.3. 事务相关信息
- xmin:插入该行版本的事务ID
- xmax:删除此行的事务ID,第一次插入时为0。如果查询出来不为0,则可能是删除该行的事务还没有提交,或者是删除此行的事务回滚掉了
- cmin:事务内部插入类操作的命令ID,从0开始
- cmax:事务内部删除类的命令ID,如果不是删除命令,值为0
- ctid:一个行版本在它所处表内的物理位置
3.4. 事务实现
- 每行上有xmin和xmax两个系统字段
- 当插入一行数据时,将这行上的xmin设置为当前的事务id,而xmax设置为0
- 当更新一行时,实际上是插入新行,把旧行上的xmax设置为当前事务id,新插入行的xmin设置为当前事务id,新行的xmax设置为0
- 当删除一行时,把当前行的xmax设置为当前事务id
- 当读到一行时,查询xmin和xmax对应的事务状态是否是已提交还是回滚了, 就能判断出此行对当前行是否是可见。
大批量的死亡版本数据带来的问题就是表膨胀。—autovacuum进程,手动vacuum
autovacuum进程,默认开启
3.5. 事务可见性判定
3.6. VACUUM
- autovacuum (boolean)
autovacuum参数控制 autovacuum 进程是否打开,默认为 “on” - log_autovacuum_min_duration(integer)
这个参数用来记录 autovacuum 的执行时间,当 autovaccum 的执行时间超过参数设置时,则autovacuum信息记录到日志里,默认为 “-1”, 表示不记录 - autovacuum_max_workers (integer)
指定同时运行的 最大的 autovacuum 进程,默认为3个。 - autovacuum_naptime (integer)
指定 autovacuum 进程运行的最小间隔,默认为 1 min。也就是说当前一个 autovacuum 进程运行完成后,第二个 autovacuum 进程至少在一分钟后才会运行。