0%

pg_dump/pg_dumpall属于一致性逻辑备份,可以用其进行跨PostgreSQL版本,跨系统平台的数据迁移。用于常规备份则其速度和灵活性略显不足。

而连续归档模式则类似于oracle的rman备份方式,可用于大型数据库的增量备份和恢复,以及用于搭建高可用standby镜像备份。

设置归档

PostgreSQL默认处于非归档模式。开启归档模式,主要涉及到三个参数:wal_level,archive_mode和archive_command

wal_level参数默认为mininal,设置此参数为archive或者之上的级别都可以打开归档。
当postgresql需要传输归档日志时,会调用archive_command指定的shell命令。归档文件传输成功时,shell命令要返回0,此时,postgresql会认为归档文件已经传输成功,因此可以删除或者重新循环利用归档文件。当shell命令返回非0值时,postgresql会保留所有未成功传输的归档日志,并不断尝试重新传输,直到成功。如果归档命令一直不成功,pg_xlog目录会持续增长,有耗尽服务器存储空间的可能,此时postgresql会PANIC关闭,直到释放存储空间。

将归档WAL日志存储在本机上是风险极高,不被推荐的。postgresql通过archive_command提供了存储WAL日志的灵活性,可以将归档日志存储到挂装的NFS目录,磁带,刻录到光盘,也可以将WAL日志通过ssh/scp传输到异机保存。

要注意,archive_command将以运行PostgreSQL的系统用户的身份运行。debian系统里,这个系统用户是postgres。

修改/etc/postgresql/$PG_VERISON/main/postgresql.conf文件以启动归档:

1
2
3
4
wal_level = archive
archive_mode = on
#archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
archive_command = 'ssh arc_svr test ! -f /path/to/archive/%f && scp %p arc_svr:/path/to/archive/%f'

arc_svr是用于存储WAL日志的ssh服务器别名
然后重新启动postgresql

1
$ sudo service postgresql restart

手动切换WAL日志,看配置是否正确,WAL是否正确传输了:

1
2
3
4
5
$ sudo -u postgres psql -c 'select pg_switch_xlog()'
pg_switch_xlog
----------------
1/6A0006A8
(1 row)

查看归档目录下出现了归档WAL日志文件。

使用pg_start_backup进行基础备份

  1. 确保postgesql运行于归档模式

    1
    2
    3
    4
    5
    6
    7
    8
    postgres=# select name, setting from pg_catalog.pg_settings where name like 'archive%' or name = 'wal_level';
    name setting
    -----------------+---------------------------------------------------------------------------
    archive_command ssh node5 test ! -f /var/backups/postgresql/archive/%f && scp %p node5:/var/backups/postgresql/archive/%f
    archive_mode on
    archive_timeout 0
    wal_level archive
    (4 rows)
  2. 使用超级用户执行pg_start_backup

    1
    2
    3
    4
    5
    postgres=# select pg_start_backup('basebackup-20151205');
    pg_start_backup
    -----------------
    1/6F000028
    (1 row)

    basebackup-20151205是一个标签,用户自行指定用于标识本次基础备份。pg_start_backup会创建一个备份标签文件(backup label file),文件内保存有此次基本备份的相关信息。

  3. 使用文件系统备份工具备份整个集群的数据文件

    1
    2
    3
    4
    5
    6
    7
    $ sudo -u postgres tar cjvf /var/backups/postgresql/base/20151205.tbz2 -P \\
    --exclude=/var/lib/postgresql/9.4/main/postmaster.pid \\
    --exclude=/var/lib/postgresql/9.4/main/postmaster.opts \\
    --exclude=/var/lib/postgresql/9.4/main/pg_xlog \\
    --exclude=/var/lib/postgresql/9.4/main/pg_replslot \\
    --warning=no-file-changed --warning=no-file-removed \\
    /var/lib/postgresql/9.4/main

备份时需要排除掉postmaster.pid和postmaster.opts文件,以及pg_xlog和pg_replslot目录。

生成的基础备份应该与归档WAL日志采用一样的存储策略,存储到异机保存,并可以进一步保存到永久介质保存,比如磁带或者CDROM。
4. 以超级用户身份执行pg_stop_backup

1
2
3
4
5
6
postgres=# select pg_stop_backup();
NOTICE: pg_stop_backup complete, all required WAL segments have been archived
pg_stop_backup
----------------
1/6F1A64F8
(1 row)

pg_stop_backup会将备份期间活动的WAL日志文件归档,一旦这些日志完成归档,则整个备份过程就结束了。
pg_stop_backup会生成一个.backup文件标识出保证此次备份完整性所需要的最后一个WAL日志,使用此次基础备份恢复系统时,不再需要之前的WAL日志。
比如:

1
2
-rw------- 1 admin admin 306 Dec 5 21:37 00000001000000010000006F.00000028.backup
-rw------- 1 admin admin 16M Dec 5 21:37 00000001000000010000006F

说明此次备份所需的归档WAL日志文件从00000001000000010000006F往后即可,包含此文件和对应的.backup文件。
backup文件的内容类似如下:

1
2
3
4
5
6
7
8
START WAL LOCATION: 1/6F000028 (file 00000001000000010000006F)
STOP WAL LOCATION: 1/6F1A64F8 (file 00000001000000010000006F)
CHECKPOINT LOCATION: 1/6F000028
BACKUP METHOD: pg_start_backup
BACKUP FROM: master
START TIME: 2015-12-05 21:03:03 CST
LABEL: basebackup-20151205
STOP TIME: 2015-12-05 21:37:58 CST

使用pg_basebackup进行基础备份

pg_basebackup使用复制协议,因此需要配置pg_hba.conf文件以允许replication连接,无论本地还是通过网络。
比如:

1
2
local replication postgres peer 
host replication postgres 192.168.0.0/24 md5

还需要设置postgresql.conf文件中的max_wal_senders参数以允许至少一个session连接来进行备份。
修改两个参数文件后,重新启动postgresql。

然后执行以下命令:

1
2
3
4
5
$ sudo -u postgres pg_basebackup -RPv -X fetch -D baseback20151205-1 
transaction log start point: 1/72000028 on timeline 1
498974/498974 kB (100%), 1/1 tablespace
transaction log end point: 1/72000430
pg_basebackup: base backup completed

这会生成一个备份目录,其目录结构与数据库集群的目录结构一致。如果要将数据打包到一个bz2文件,可以执行如下命令:

1
$ sudo -u postgres sh -c 'pg_basebackup -RPv -Ft -D - -X fetch | bzip2 > baseback20151205-1.tbz2'

请注意输出文件的写入权限

pg_basebackup命令同样会在备份中生成backup_label文件和.backup归档日志文件。
其.backup文件内容类似如下:

1
2
3
4
5
6
7
8
START WAL LOCATION: 1/7C000028 (file 00000001000000010000007C)
STOP WAL LOCATION: 1/7C000998 (file 00000001000000010000007C)
CHECKPOINT LOCATION: 1/7C000550
BACKUP METHOD: streamed
BACKUP FROM: master
START TIME: 2015-12-05 22:52:23 CST
LABEL: pg_basebackup base backup
STOP TIME: 2015-12-05 22:53:20 CST

可以远程使用pg_basebackup来进行基础备份。

pg_basebackup的详细参数见man pg_basebackup或参考[2]。

References:
[1]24.3. Continuous Archiving and Point-in-Time Recovery (PITR)
[2]pg_basebackup

KVM qcow2格式镜像文件转换为VirtualBox VDI格式镜像文件,转换完毕后,可以使用VirtualBox直接启动虚拟机:

1
$ qemu-img convert -f qcow2 foo.qcow2 -O vdi foo.vdi

intel迅驰无线网卡Centrino Wireless-N 2200在debian jessie系统下奇慢无比,连接速度只有1Mb/s,到网关的延迟有时达到1000ms以上。

是因为此无线网卡在802.11n模式下与当前内核存在兼容性问题。所以,要解决此问题,要么关闭无线网卡的802.11n模式,或者更改无线路由器不开启802.11n模式。

关闭网卡的802.11n工作模式

/etc/modprobe.d目录下新建文件11n_disable.conf,添加如下行:

1
options iwlwifi 11n_disable=1

重新启动机器。

References:
[1]Intel Centrino Wireless-N 2200 Ubuntu 1Mbps Workaround
[2]How to fix slow wireless on machines with Intel wireless cards?

===
[erq]

Mac OS X 10.11连接linux系统CUPS使用ipp(Internet Printing Protocol)协议共享的打印机时,遇到两个大坑。

系统打印机配置的坑

使用mac系统的打印机配置来连接共享打印机
从System Preferences->Printers & Scanners对话框添加ip打印机,选择IPP协议,address输入正确的共享打印机地址:

1
2
3
4
5
6
http://printer_server_ip:631/printers/HP_LaserJet_P1008
```
无论使用何种驱动,add时都会有提示:
```js
Unable to verify the printer on your network.
Unable to connect to ‘printer_server_ip’ due to an error. Would you still like to create the printer?

如果强制添加,然而并不能真的打印
事后发现mac os x 10.11系统打印机配置添加的ipp打印机访问地址是错误的,可以通过cups配置界面看到其错误的地址。

HP官方驱动的坑

一直以为官方驱动应该是最靠谱的,不过这次不行。
已经提前安装了HP Mac OS X drivers,500多M!

改用cups来添加共享打印机。
mac上的cups默认是没有打开web管理界面的,首先启用web管理界面:

1
$ cupsctl WebInterface=yes

然后访问http://127.0.0.1:631打开cups管理界面来添加远程ipp协议共享打印机。

Administration->Printer->Add Printer->Other Network Printers->Internet Printing Protocol(http)

输入ipp打印机的访问地址:

1
http://printer_server_ip:631/printers/HP_LaserJet_P1008

选择HP提供的P1008官方驱动,添加完成。

然而并不能打印!

重新修改已添加打印机配置,Printers->P1008->Modify Printer将其驱动更改为cups内置的Generic PostScript Printer

打印测试页,success!

References:
[1]Internet Printing Protocol
[2]Line Printer Daemon protocol
[3]About AirPrint
[4]PostScript Printer Description

===
[erq]

cassandra像其他RDBMS一样提供了export/import工具:

  • cqlsh命令COPY TO/FROM
    注意这不是cql命令。使用这组命令可以在cassandra与其他RDBMS或cassandra之间迁移数据。COPY TO/FROM支持CSV文件格式以及标准输出和输入。
    COPY TO/FROM命令同样支持集合数据类型。
  • sstable2json/json2sstable
    这组工具已经过时,在3.0版本中已被删除。所以不应该再使用这组工具。
  • sstableloader
    Cassandra bulk loader,可以装载外部数据到cassandra,也可以恢复snapshot,装载sstable到不同配置的cassandra集群。
    如果数据量很大,应该使用sstableloader,如果数据量比较小的话,使用COPY TO/FROM更省时省力。
  • Snapshots
    snapshots是cassandra正牌的备份恢复工具,而不是用于与其他数据库系统进行数据迁移的工具。所以严格来说它不应该算作export/import工具。
  • ETL工具
    很多第三方的ETL(Extract-Transform-Load)工具支持从其他数据库向cassandra数据库迁移数据。

COPY TO/FROM

这里只讲一下COPY TO/FROM命令。

命令格式:

1
2
3
4
5
6
7
COPY table_name ( column, ...)
FROM ( 'file_name' STDIN )
WITH option = 'value' AND ...

COPY table_name ( column , ... )
TO ( 'file_name' STDOUT )
WITH option = 'value' AND ...

COPY FROM 用于从csv文件或标准输入import数据到表,而COPY TO用于将表数据export到csv文件或标准输出。

WITH option=’value’ 用于指定csv文件的格式,分隔符,引用,转移字符,文件编码,时间格式等等,详见官方文档。

如果不指定列名,会按表元数据中记载的列顺序输出所有的列。同样,如果csv也是按相同的顺序组织数据,COPY FROM时也可以忽略所有的列名。

COPY TO/FROM时,可以只指定部分列进行部分数据的导出和导入,而且可以以任意顺序指定列名。

如果表中已经存在数据,COPY FROM不会truncate已有的数据。

导出数据的示例:

1
2
cqlsh> use test ;
cqlsh> COPY airplanes (name, mach, year, manufacturer) TO 'export.csv' ;

导入数据的示例:

1
cqlsh> COPY airplanes (name, mach, year, manufacturer) FROM 'import.csv' ;

如果使用标准输入导入数据,要使用只包含 \. 字符的单独一行来结束数据输入。

如果导入数据时出现如下错误提示:

1
2
3
4
Error starting import process:

field larger than field limit (131072)
%d format: a number is required, not NoneType

这是因为csv文件包含大容量字段,python的csv模块需要设置更大的字段尺寸限制。

修改/usr/bin/cqlsh.py文件,在导入csv模块之后,添加如下行:

1
csv.field_size_limit(sys.maxsize)

注意:含有counter列的表无法使用COPY TO/FROM来导出和导入数据。

References:
[1]Ways to Move Data To/From DataStax Enterprise and Cassandra
[2]Consider deprecating sstable2json/json2sstable in 2.2
[3]_csv.Error: field larger than field limit (131072)
[4]cassandra数据迁移

===
[erq]

GNOME环境下的GUI应用程序可以配置在GNOME初始化后自动运行。

配置自启动的位置在:

1
$HOME/.config/autostart/

简单的将/usr/share/applications目录下的.desktop文件拷贝到此目录下即可:

1
$ cp /usr/share/applications/foo.desktop ~/.config/autostart/

或者使用GNOME Tweak Tool -> Startup Applications选择一下就可以了。

References:
[1]Autostarting

===
[erq]

Dumps created by pg_dump are internally consistent, meaning, the dump represents a snapshot of
the database at the time pg_dump began running. pg_dump does not block other operations on the
database while it is working. (Exceptions are those operations that need to operate with an exclusive
lock, such as most forms of ALTER TABLE .)

手工创建oracle数据库,新建用户sqlplus登录时有错误提示信息:

1
2
3
4
5
6
7
ERROR:
ORA-00942: table or view does not exist


Error accessing PRODUCT_USER_PROFILE
Warning: Product user profile information not loaded!
You may need to run PUPBLD.SQL as SYSTEM

可以正常登录,不影响使用。

用system用户登录数据库,执行脚本$ORACLE_HOME/sqlplus/admin/pupbld.sql可以消除此错误提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
$ sqlplus system/xxxx@orcl
SQL>@/u01/app/oracle/product/10.2.0/db_1/sqlplus/admin/pupbld.sql

DROP SYNONYM PRODUCT_USER_PROFILE
*
ERROR at line 1:
ORA-01434: private synonym to be dropped does not exist

DATE_VALUE FROM PRODUCT_USER_PROFILE
*
ERROR at line 3:
ORA-00942: table or view does not exist

DROP TABLE PRODUCT_USER_PROFILE
*
ERROR at line 1:
ORA-00942: table or view does not exist

ALTER TABLE SQLPLUS_PRODUCT_PROFILE ADD (LONG_VALUE LONG)
*
ERROR at line 1:
ORA-00942: table or view does not exist

Table created.

DROP TABLE PRODUCT_PROFILE
*
ERROR at line 1:
ORA-00942: table or view does not exist

DROP VIEW PRODUCT_PRIVS
*
ERROR at line 1:
ORA-00942: table or view does not exist

View created.

Grant succeeded.

DROP PUBLIC SYNONYM PRODUCT_PROFILE
*
ERROR at line 1:
ORA-01432: public synonym to be dropped does not exist

Synonym created.

DROP SYNONYM PRODUCT_USER_PROFILE
*
ERROR at line 1:
ORA-01434: private synonym to be dropped does not exist

Synonym created.

DROP PUBLIC SYNONYM PRODUCT_USER_PROFILE
*
ERROR at line 1:
ORA-01432: public synonym to be dropped does not exist

Synonym created.

重新登录新用户,错误提示消失。

===
[erq]

When updating to a new minor release, the safest policy is to update the standby servers first — a new minor release is more likely to be able to read WAL files from a previous minor release than vice versa. — postgresql high availability

命名格式

版本号的命名格式为:

主版本号.次版本号[-发布进程版本号]-修订版本号-发布分支头SHA1 ID

管理策略

主版本号(Major)和次版本号(Minor):

主版本号对应大的、全局功能更新,而次版本号对应小的、局部的功能更新。主、次版本号根据实际情况设定。

发布进程版本号(release):

用于标识发布进程的版本号后缀,使用alpha(内部测试),beta(公共测试)和rc(release candidate,发布候选)加上数字作为次版本号的后缀,比如alpha1,alpha2,beta1,beta2,rc1,rc2等。

修订版本号:

标识自上次标定主次版本号以来的bugfix次数。修订版本号不涉及功能更新。每次重新标定主、次版本号(还可能有发布进程版本号)之后,修订版本号重置,从0开始重新计数。

发布分支头sha1:

标识该版本对应的发布分支头提交的sha1摘要,方便通过版本号回溯git代码库中的commit。

实现

主、次、发布进程版本号,根据项目实际情况确定,确定之后在发布分支上打标签以记录版本号:

1
$ git tag -a v1.0-rc1 -m 'version 1.0 release candidate 1'

修订版本号和发布分支头sha1 id通过git命令describe来自动生成:

1
$ git describe --tags --long

最后会生成如下格式的版本号:

1
v1.0-rc1-10-g742aee8

此版本号的含义为:主版本号为1,次版本号为0,发布进程版本号为rc1,修订版本号为10,也就是主、次、发布进程版本号设定之后又进行了10次bugfix,发布分支头为742a3ee8这个commit对象。

构建

在自动构建脚本中调用git describe命令来自动生成版本号,并自动记录到应用程序中,最后发布的应用程序就有了明确的、易于追溯的版本号。

===
[erq]