今天看到有人问“PostgreSQL中的copy命令是在同一个事务中执行的吗”。其实我想之所以提出这个问题,主要是想知道在执行copy语句时如果出现错误导致中断,那么数据是会导出/入部分,还是会像事务一样回滚。为了解答这个问题,我们先来简单了解下copy协议。

什么是copy协议?

我们使用客户端和数据库进行交互时,都必须要遵守PostgreSQL数据库的通信协议才可以。让我们比较熟悉的协议有TCP/IP 协议和 HTTP 协议等。

而PostgreSQL在TCP/IP 协议之上实现了一套基于消息的通信协议,同时,为避免客户端和服务端在同一台机器时的网络通信代价,也支持在 Unix 域套接字上使用该协议。

我们要说的copy协议就是这些通信协议的一种,但不同于普通的与数据库交互的协议,copy协议是专门为了高效地导入/导出数据,当我们执行copy操作时会将当前连接切换至一种截然不同的子协议。

Copy 子协议对应三种模式:

  • copy-in:导入数据,对应命令 COPY FROM STDIN
  • copy-out:导出数据,对应命令 COPY TO STDOUT
  • copy-both:用于 walsender,在主备间批量传输数据

copy协议简介

我们以copy-in为例,先看一下相关的消息格式。

copy-inCopyInResponse:

  • Byte1(‘G’):标识这条消息是一条Start Copy
    In(开始拷贝入)响应消息。前端现在必须发送拷贝入数据(如果还没准备好做这些事情,那么发送一条CopyFail消息)。
  • Int32:以字节计的消息内容的长度,包括长度本身。
  • Int8:0表示全体拷贝格式都是文本(数据行由新符分隔, 列由分隔字符分隔等等)。1 表示全体拷贝格式都是二进制的(类似于DataRow
    格式)。
  • Int16:要拷贝的数据中的列数
  • Int16[N]:每个列要使用的格式代码。目前每个都必须是零(文本)或者一(二进制)。 如果全体拷贝格式都是文本,那么所有的都必须是零。

CopyData:

  • Byte1(‘d’):标识这条消息是一个COPY数据。
  • Int32:以字节计的消息内容的长度,包括长度本身。
  • data:构成COPY数据流的一部分的数据。从后端发出的消息总是对应单一的数据行,但是前端发出的消息可能会任意分割数据流。

以copy-in为例,其大致流程如下:

服务端收到 COPY 命令后,进入 COPY 模式,并回复 CopyInResponse。随后客户端通过 CopyData 消息传输数据,CopyComplete 消息标识数据传输完成,服务端收到该消息后,发送 CommandComplete 和 ReadyForQuery 消息。

copy与事务:

和普通的insert语句不同,copy是在一条命令里加载所有记录, 而不是一连串的INSERT命令。
因此其本质上和事务是类似的,但是和事务还是有很大区别。

在事务中,如果我们遇到错误会停止,然后回滚这个事务,而copy会在遇到错误时中止,但是不是简单的回滚。
如果是copy to,那么则出现错误前的数据不会受影响;而如果是copy from,那么在出现错误前的数据在目标表中会变的不可见,这个并不是说回滚了,而是不可见或者不可访问,所以这部分数据在目标表中仍然占用磁盘空间。

例子:
–copy to:

我们可以看到表t1中有1000W条数据,copy到文件大小为390M

bill@bill=>copy t1 to '/home/pg13/t1.sql';
COPY 10000000pg13@cnndr4pptliot-> du -sh t1.sql
390M    t1.sql

重新copy,然后中断该操作,发现只有部分数据被copy to文件中了,说明中断前的数据没受到影响。

bill@bill=>copy t1 to '/home/pg13/t1.sql';
^CCancel request sent
ERROR:  canceling statement due to user requestpg13@cnndr4pptliot-> du -sh t1.sql
362M    t1.sql

–copy from:
copy时进行中断。

bill@bill=>truncate table t1;
TRUNCATE TABLEbill@bill=>copy t1 from '/home/pg13/t1.sql';
^CCancel request sent
ERROR:  canceling statement due to user request
CONTEXT:  COPY t1, line 5260603: "4539963       4dbe984c7a23aa2674d5d1fcd82f1b91"

查看:
发现表中没有任何数据,但是大小为374MB!

bill@bill=>select count(*) from t1;count
-------0
(1 row)bill@bill=>\dt+ t1List of relationsSchema | Name | Type  | Owner | Persistence |  Size  | Description
--------+------+-------+-------+-------------+--------+-------------public | t1   | table | bill  | permanent   | 374 MB |
(1 row)

日志:

2021-07-14 11:34:58.527 CST,,,28662,,60ee5b60.6ff6,1,,2021-07-14 11:34:56 CST,4/3245,3897,LOG,00000,"automatic vacuum of table ""bill.public.t1"": index scans: 0
pages: 47859 removed, 0 remain, 0 skipped due to pins, 0 skipped frozen
tuples: 5743000 removed, 0 remain, 0 are dead but not yet removable, oldest xmin: 3897
buffer usage: 52219 hits, 91400 misses, 45729 dirtied
avg read rate: 395.184 MB/s, avg write rate: 197.717 MB/s
system usage: CPU: user: 0.51 s, system: 0.62 s, elapsed: 1.80 s
WAL usage: 143579 records, 2 full page images, 30980935 bytes",,,,,,,,"heap_vacuum_rel, vacuumlazy.c:691","","autovacuum worker"

再次查看:
可以看到日志中,当该表被vacuum后,表占用的磁盘空间便被回收了。

bill@bill=>\dt+ t1List of relationsSchema | Name | Type  | Owner | Persistence | Size  | Description
--------+------+-------+-------+-------------+-------+-------------public | t1   | table | bill  | permanent   | 24 kB |
(1 row)

总结:

通过上面的实验我们可以的出结论,对于copy操作,如果中途出现问题导致中断:

  • copy to:不会受到影响,中断前已经copy的数据仍然有效;
  • copy from:目标表中已经拷贝的数据会变得不可见,但是仍然占用磁盘空间,等到被vacuum时空间将被回收。

参考链接:
https://www.pgcon.org/2014/schedule/attachments/330_postgres-for-the-wire.pdf
http://www.postgres.cn/docs/13/sql-copy.html
http://www.postgres.cn/docs/13/protocol-message-formats.html

PostgreSQL copy协议与事务相关推荐

  1. PostgreSQL 随读笔记-事务上

    PostgreSQL 随读笔记-事务 7. 事务处理与并发控制 7.1 事务系统简介 事务管理器 是事务系统的中枢,本事是一个FSM.通过接受外部系统的命令或者信号,再根据当前事务所处的状态决定事务的 ...

  2. PostgreSQL copy 命令教程

    报文介绍PostgreSQL copy 命令,通过示例展示把查询结果导出到csv文件,导入数据文件至postgresql. 1. copy命令介绍 copy命令用于在postgreSql表和标准文件系 ...

  3. postgresql copy from、copy to

    postgresql的copy命令用来在文件和表之间进行数据复制,复制效率很高. 官方提供了命令行的copy命令以及Java封装的copy,下文将分别介绍说明. 命令行copy copy有两个命令:C ...

  4. 四、redi性能测试、协议、事务

    一.redis慢查询 慢查询的作用:通过慢查询分析,找到有问题的命令进行优化. Redis slowlog是Redis用来记录查询执行时间的日志系统. 查询执行时间指的是不包括像客户端响应(talki ...

  5. POSTGRESQL COPY 命令导入数据,你还另一个更快的方案!

    POSTGRESQL 数据库数据导入的核心一般都使用COPY 命令,熟悉POSTGRESQL 的同学应该对这个命令不陌生,相对于MYSQL 去一条条的执行insert命令来说,COPY 命令是POST ...

  6. PostgreSQL COPY 导入/导出数据

    COPY 命令可以快速的导入数据到 PostgreSQL 中,文件格式类似CVS之类.适合批量导入数据,比 \i 和恢复数据表快. 导出表数据到文件或 STDOUT : COPY tablename ...

  7. PostgreSQL的clog—从事务回滚速度谈起

    如果是之前学习别的数据库的人,看PostgreSQL会感觉到有句话非常奇怪:"PostgreSQL的回滚是立即完成的,不会受到事务大小本身的影响". 奇怪在哪里呢?比方我曾经遇到过 ...

  8. SIP协议之事务(transaction)及INVITE事务

    一.SIP事务   SIP事务(SIP Transaction):SIP 事务发生在客户端和服务器之间并且由从第一个从客户端发送到服务器的请求直到最后一个.   SIP协议是一个事务协议,组件间的交互 ...

  9. postgresql copy语句

    总述 copy命令用于在postgreSql表和标准文件系统直接传输数据. copy命令让PostgreSQL 服务器直接读写文件,因此文件必须位于服务器本地或能被直接访问. 该命令仅能在表上使用,不 ...

最新文章

  1. 提示以演示模式运行_德事隆和IMSAR在小型无人机上集成并演示合成孔径雷达
  2. 丢弃掉那些BeanUtils工具类吧,MapStruct真香!!!
  3. python发明者叫什么-看看9种编程语言的发明者是怎么说的
  4. 【零基础】Python的入门学习
  5. hdu4035 Maze 【期望dp + 数学】
  6. Jquery有哪些选择器
  7. nginx修改upstream不重启的方法(ngx_http_dyups_module模块)
  8. eclipse鼠标变十了_Eclipse在过去十年中的主要成就
  9. 第一次作业源于计科一班的王相博
  10. 虚拟机安装mac os x实战
  11. 转折后的总结--2014年找工作
  12. Node.js「一」—— Node.js 简介 / Node.js 模块 / 包 与 NPM
  13. linux职业_对Linux的好奇心导致了意外的职业
  14. 文字虚线怎么去掉_PS十秒钟更改图片上的文字?没问题!这个小技巧你轻松get到手「16期」...
  15. aws s3 连接建立
  16. Atitit db access req数据库访问规范jdo jdbc jpa pdo sql 目录 1. 常见特性 1 1.1. 元数据 API 1 1.2. 分布式事务 vs事务中使用 Sav
  17. 星环Transwarp Data Hub大数据安装学习
  18. 玩转微信个性化头像,一键加V/加字/加图片
  19. 瞬态抑制二极管 tvs 二极管参数选型
  20. 微软关闭Win7所有服务器,微软公布Win7彻底退役时间 将于2020年终止所有支持

热门文章

  1. 关于Mysql中的不等于
  2. 大学计算机课作文,微机课作文400
  3. 华泰交易钩子之dll 2021-02-25
  4. s8更新系统提示网络或服务器出错,更新不用愁!王者荣耀S8更新错误问题代码全指引...
  5. 电阻,电容,电感(resistor, capacitor, inductor)
  6. 1949: 没名字的题
  7. java jdk win2003_Windows XP/2003下JDK的安装
  8. 在下列计算机应用技术中,计算机应用与技术试卷A及答案供参考
  9. variant conversion error for variable v23
  10. [dp算法]逃离农场