-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy path4.4.html
More file actions
2398 lines (2357 loc) · 152 KB
/
4.4.html
File metadata and controls
2398 lines (2357 loc) · 152 KB
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>运维管理指南 :: IvorySQL文档中心</title>
<link rel="canonical" href="https://docs.ivorysql.org/ivorysql-doc/master/4.4.html">
<link rel="prev" href="4.3.html">
<link rel="next" href="4.5.html">
<meta name="generator" content="Antora 3.1.7">
<link rel="stylesheet" href="../../_/css/site.css">
<script>var uiRootPath = '../../_'</script>
</head>
<body class="article">
<header class="header">
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="https://docs.ivorysql.org">IvorySQL文档中心</a>
<div class="navbar-item search hide-for-print">
<div id="search-field" class="field">
<input id="search-input" type="text" placeholder="Search the docs">
</div>
</div>
<button class="navbar-burger" data-target="topbar-nav">
<span></span>
<span></span>
<span></span>
</button>
</div>
<div id="topbar-nav" class="navbar-menu">
<div class="navbar-end">
<a class="navbar-item" href="https://www.ivorysql.org/">官方网站</a>
</div>
</div>
</nav>
</header>
<div class="body">
<div class="nav-container" data-component="ivorysql-doc" data-version="master">
<aside class="nav">
<div class="panels">
<div class="nav-panel-menu is-active" data-panel="menu">
<nav class="nav-menu">
<h3 class="title"><a href="welcome.html">文档中心</a></h3>
<ul class="nav-list">
<li class="nav-item" data-depth="0">
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<span class="nav-text">IvorySQL</span>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="welcome.html">欢迎</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="1.html">发行说明</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="2.html">关于IvorySQL</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">IvorySQL入门</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="3.1.html">快速开始</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="3.2.html">日常监控</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="3.3.html">日常维护</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">IvorySQL高级</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="4.1.html">安装指南</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="4.2.html">集群搭建</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="4.3.html">开发者指南</a>
</li>
<li class="nav-item is-current-page" data-depth="3">
<a class="nav-link" href="4.4.html">运维管理指南</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="4.5.html">迁移指南</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">IvorySQL生态</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="5.1.html">PostGIS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="5.2.html">pgvector</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">IvorySQL架构设计</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<span class="nav-text">查询处理</span>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="6.1.1.html">双parser</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<span class="nav-text">兼容框架</span>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="6.2.1.html">initdb过程</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<span class="nav-text">兼容特性</span>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="6.3.1.html">like</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="6.3.3.html">RowID</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="6.3.2.html">OUT 参数</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="6.3.4.html">%TYPE、%ROWTYPE</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="6.4.html">国标GB18030</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Oracle兼容功能列表</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.1.html">1、框架设计</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.2.html">2、GUC框架</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.3.html">3、大小写转换</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.4.html">4、双模式设计</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.5.html">5、兼容Oracle like</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.6.html">6、兼容Oracle匿名块</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.7.html">7、兼容Oracle函数与存储过程</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.8.html">8、内置数据类型与内置函数</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.9.html">9、新增Oracle兼容模式的端口与IP</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.10.html">10、XML函数</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.11.html">11、兼容Oracle sequence</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.12.html">12、包</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.13.html">13、不可见列</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.14.html">14、RowID</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.15.html">15、OUT 参数</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="7.16.html">16、%TYPE、%ROWTYPE</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">IvorySQL贡献指南</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="8.1.html">社区贡献指南</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="8.2.html">asciidoc语法快速参考</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="9.html">工具参考</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="10.html">FAQ</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<span class="nav-text">PostgreSQL</span>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="100.html">PG参数参考手册</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="110.html">PG函数参考手册</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<div class="nav-panel-explore" data-panel="explore">
<div class="context">
<span class="title">文档中心</span>
<span class="version">master</span>
</div>
<ul class="components">
<li class="component is-current">
<a class="title" href="welcome.html">文档中心</a>
<ul class="versions">
<li class="version is-current is-latest">
<a href="welcome.html">master</a>
</li>
<li class="version">
<a href="../v4.6/v4.6/welcome.html">v4.6</a>
</li>
<li class="version">
<a href="../v4.5/v4.5/welcome.html">v4.5</a>
</li>
<li class="version">
<a href="../v4.4/v4.4/welcome.html">v4.4</a>
</li>
<li class="version">
<a href="../v4.2/v4.2/welcome.html">v4.2</a>
</li>
<li class="version">
<a href="../v4.0/v4.0/welcome.html">v4.0</a>
</li>
<li class="version">
<a href="../v3.4/v3.4/welcome.html">v3.4</a>
</li>
<li class="version">
<a href="../v3.3/v3.3/welcome.html">v3.3</a>
</li>
<li class="version">
<a href="../v3.2/v3.2/welcome.html">v3.2</a>
</li>
<li class="version">
<a href="../v3.1/v3.1/welcome.html">v3.1</a>
</li>
<li class="version">
<a href="../v3.0/v3.0/welcome.html">v3.0</a>
</li>
<li class="version">
<a href="../v2.3/v2.3/welcome.html">v2.3</a>
</li>
<li class="version">
<a href="../v2.2/v2.2/welcome.html">v2.2</a>
</li>
<li class="version">
<a href="../v2.1/v2.1/welcome.html">v2.1</a>
</li>
<li class="version">
<a href="../v1.17/v1.17/welcome.html">v1.17</a>
</li>
<li class="version">
<a href="../v1.8/v1.8/welcome.html">v1.8</a>
</li>
<li class="version">
<a href="../v1.5/v1.5/welcome.html">v1.5</a>
</li>
<li class="version">
<a href="../v1.4/v1.4/welcome.html">v1.4</a>
</li>
<li class="version">
<a href="../v1.3/v1.3/welcome.html">v1.3</a>
</li>
<li class="version">
<a href="../v1.2/v1.2/welcome.html">v1.2</a>
</li>
<li class="version">
<a href="../v1.1/v1.1/welcome.html">v1.1</a>
</li>
<li class="version">
<a href="../v1.0/v1.0/welcome.html">v1.0</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</aside>
</div>
<main class="article">
<div class="toolbar" role="navigation">
<button class="nav-toggle"></button>
<nav class="breadcrumbs" aria-label="breadcrumbs">
<ul>
<li><a href="welcome.html">文档中心</a></li>
<li>IvorySQL</li>
<li>IvorySQL高级</li>
<li><a href="4.4.html">运维管理指南</a></li>
</ul>
</nav>
<div class="page-versions">
<button class="version-menu-toggle" title="switch to English">CN</button>
<div class="version-menu">
<a class="version is-current" href="">CN</a>
<a class="version" href="../../../../en/ivorysql-doc/master/4.4.html">EN</a>
</div>
</div>
<div class="edit-this-page"><a href="https://github.com/IvorySQL/ivorysql_docs/edit/master/CN/modules/ROOT/pages/master/4.4.adoc">编辑此页面</a></div>
</div>
<div class="content">
<aside class="toc sidebar" data-title="目录" data-levels="2">
<div class="toc-menu"></div>
</aside>
<article class="doc">
<h1 class="page">运维管理指南</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>由于IvorySQL基于PostgreSQL开发而成,运维人员在阅读理解本节内容时,建议同时参阅 <a href="https://www.postgresql.org/docs/17/index.html">手册</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="升级ivorysql版本"><a class="anchor" href="#升级ivorysql版本"></a>1. 升级IvorySQL版本</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="升级方案概述"><a class="anchor" href="#升级方案概述"></a>1.1. 升级方案概述</h3>
<div class="paragraph">
<p>IvorySQL版本号由主要版本和次要版本组成。例如,IvorySQL 3.2 中的3是主要版本,2是次要版本。</p>
</div>
<div class="paragraph">
<p>发布次要版本是不会改变内存的存储格式,因此总是和相同的主要版本兼容。例如,IvorySQL 3.2 和Ivory SQL 3.0 以及后续的 Ivory SQL 3.x 兼容。对于这些兼容版本的升级非常简单,只要关闭数据库服务,安装替换二进制的可执行文件,重新启动服务即可。</p>
</div>
<div class="paragraph">
<p>接下来,我们主要讨论IvorySQL的跨版本升级问题,例如,从 IvorySQL 2.3 升级到 IvorySQL 3.4 。主要版本的升级可能会修改内部数据的存储格式,因此需要执行额外的操作。常用的跨版本升级方法和适用场景如下:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">升级方法</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">适用场景</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">停机时间</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">通过pg_dumpall升级数据</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">中小型数据库,例如小于100GB支持跨平台数据迁移</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">取决于数据库的大小</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">pg_upgrade工具</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">大中型数据库,例如大于100GB本机就地升级</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">几分钟</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">逻辑复制</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">大中型数据库,例如大于100GB跨平台支持</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">几秒钟</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><strong>注意事项:</strong> 新的主版本通常会引入一些用户可见的不兼容性,因此可能需要应用程序编程上的改变。所有用户可见的更改都被列在 <a href="https://www.postgresql.org/docs/current/release.html">说明</a>中,请特别注意标有“Migration”的小节。尽管你可能从一个主版本升级到另一个,而不用升级中间版本,你应该阅读全部中间版本的主要发行说明。</p>
</div>
</div>
<div class="sect2">
<h3 id="通过pg_dumpall升级数据"><a class="anchor" href="#通过pg_dumpall升级数据"></a>1.2. 通过pg_dumpall升级数据</h3>
<div class="paragraph">
<p>传统的跨版本升级方法利用pg_dump/pg_dumpall逻辑备份导出数据库,然后在新版本中通过pg_restore进行还原。导出旧版本数据库时推荐使用新版本的pg_dump/pg_dumpall工具,可以利用最新的并行导出和还原功能,同时可以减少数据库膨胀问题。</p>
</div>
<div class="paragraph">
<p>逻辑备份与还原非常简单但速度比较慢,停机时间取决于数据库的大小,因此适合中小型数据库的升级。</p>
</div>
<div class="paragraph">
<p>下面介绍这种升级方法的具体操作,假如当前IvorySQL软件的安装目录位于/usr/local/pgsql,同时数据目录位于/usr/local/pgsql/data,我们在同一台服务器上进行升级。</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>执行逻辑备份之前停止应用程序,确保没有数据更新,因为备份开始后的更新不会被导出。如有必要,可以修改/usr/local/pgsql/data/pg_hba.conf文件禁止其他人访问数据库。然后备份数据库:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dumpall > outputfile</code></pre>
</div>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>如果已经安装了新版本的IvorySQL,可以使用新版本的pg_dumpall命令备份旧版本数据库。</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>2.停止旧版本的后台服务:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_ctl stop</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者通过其他方式停止后台服务。</p>
</div>
<div class="paragraph">
<p>3.如果安装目录没有包含特定版本标识,可以将目录改名,必要时可以再修改回来。可以使用类似以下的命令重命名目录:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">mv /usr/local/pgsql /usr/local/pgsql.old</code></pre>
</div>
</div>
<div class="paragraph">
<p>4.安装新版本IvorySQL软件,假如安装目录仍然是/usr/local/pgsql。</p>
</div>
<div class="paragraph">
<p>5.初始化一个新的数据库集群,需要使用数据库专用用户(通常是postgres;如果升级版本,应该已经存在该用户)执行操作:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data</code></pre>
</div>
</div>
<div class="paragraph">
<p>6.将旧版本配置文件pg_hba.conf 和 postgresql.conf 等中的改动在对应的新配置文件中再次进行修改。</p>
</div>
<div class="paragraph">
<p>7.使用数据库专用用户启动新版本的后台服务:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data</code></pre>
</div>
</div>
<div class="paragraph">
<p>8.最后利用新版本的psql命令还原数据:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">/usr/local/pqsql/bin/psql -d postgres -f outputfile</code></pre>
</div>
</div>
<div class="paragraph">
<p>为了减少停机时间,可以将新版本的IvorySQL安装到另一个目录,同时使用不同的端口启动服务。然后同时执行数据库的导出和导入:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dumpall -p 5432 | psql -d postgres -p 5433</code></pre>
</div>
</div>
<div class="paragraph">
<p>执行以上操作时,新旧版本的后台服务同时运行,新版本使用5433端口,旧版本使用5432端口。</p>
</div>
</div>
<div class="sect2">
<h3 id="利用pg_upgrade-工具进行升级"><a class="anchor" href="#利用pg_upgrade-工具进行升级"></a>1.3. 利用pg_upgrade 工具进行升级</h3>
<div class="paragraph">
<p>pg_upgrade 工具可以支持IvorySQL跨版本的就地升级。 升级可以在数分钟内被执行,特别是使用—​link模式时。它要求和上面的pg_dumpall相似的步骤,例如启动/停止 服务器、运行initdb。pg_upgrade <a href="https://www.postgresql.org/docs/current/pgupgrade.html">文档</a>概述了所需的步骤。</p>
</div>
</div>
<div class="sect2">
<h3 id="通过复制升级数据"><a class="anchor" href="#通过复制升级数据"></a>1.4. 通过复制升级数据</h3>
<div class="paragraph">
<p>我们也可以使用IvorySQL的已更新版本逻辑复制来创建一个后备服务器,逻辑复制支持在不同主版本的IvorySQL之间的复制。后备服务器可以在同一台计算机或者不同的计算机上。一旦它和主服务器(运行旧版本的IvorySQL)同步好,你可以切换主机并且将后备服务器作为主机,然后关闭旧的数据库实例。这样一种切换使得一次升级的停机时间只有数秒。</p>
</div>
<div class="paragraph">
<p>这种升级方法可以用内置的逻辑复制工具和外部的逻辑复制系统如pglogical,Slony,Londiste,和Bucardo。</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="管理ivorysql版本"><a class="anchor" href="#管理ivorysql版本"></a>2. 管理IvorySQL版本</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IvorySQL基于PostgreSQL开发,版本更新频率与PostgreSQL版本更新频率保持一致,每年更新一个大版本,每季度更新一个小版本。IvorySQL目前发布的版本有1.0到4.5,分别基于PostgreSQL 14.0到17.5进行开发,最新版本为IvorySQL 4.5,基于PostgreSQL 17.5进行开发。IvorySQL 的所有版本全部都做到了向下兼容。相关版本特性可以查看 <a href="https://www.ivorysql.org/zh-CN/releases-page">官网</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="管理ivorysql数据库访问"><a class="anchor" href="#管理ivorysql数据库访问"></a>3. 管理IvorySQL数据库访问</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IvorySQL使用 <strong>角色</strong> 的概念管理数据库访问权限。一个角色可以看成是一个数据库用户或者是数据库用户组,这取决于角色被怎样设置。角色可以拥有数据库对象(例如,表和函数)并且能够把那些对象上的权限赋予给其他角色来控制谁能访问哪些对象。此外,还可以把一个角色中的 <strong>成员资格</strong> 授予给另一个角色,这样允许成员角色使用被赋予给另一个角色的权限。</p>
</div>
<div class="paragraph">
<p>角色的概念把“用户”和“组”的概念都包括在内。</p>
</div>
<div class="paragraph">
<p>数据库角色在概念上已经完全与操作系统用户独立开来。 事实上可能维护一个对应关系会比较方便,但是这并非必需。 数据库角色在一个数据库集簇安装范围内是全局的(而不是独立数据库内)。 要创建一个角色,可使用CREATE ROLE SQL 命令:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>CREATE ROLE name;</pre>
</div>
</div>
<div class="paragraph">
<p>name遵循 SQL 标识符的规则:或是未经装饰没有特殊字符,或是用双引号包围(实际上,你将总是给该命令要加上额外选项,例如LOGIN。更多细节可见下文)。 要移除一个已有的角色,使用相似的DROP ROLE命令:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>DROP ROLE name;</pre>
</div>
</div>
<div class="paragraph">
<p>为了方便,createuser和dropuser程序被提供作为这些 SQL 命令的包装器,它们可以从 shell 命令行调用:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>createuser name
dropuser name</pre>
</div>
</div>
<div class="paragraph">
<p>要决定现有角色的集合,检查pg_roles系统目录,例如:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>SELECT rolname FROM pg_roles;</pre>
</div>
</div>
<div class="paragraph">
<p>psql程序的\du元命令也可以用来列出现有角色。</p>
</div>
<div class="paragraph">
<p>为了引导数据库系统,一个刚刚被初始化好的系统总是包含一个预定义角色。这个角色总是一个“superuser”,并且默认情况下(除非在运行initdb时修改)它的名字和初始化数据库集簇的操作系统用户相同。习惯上,这个角色将被命名为postgres。为了创建更多角色,你首先必须以初始角色的身份连接。</p>
</div>
<div class="paragraph">
<p>每一个到数据库服务器的连接都是使用某个特定角色名建立的,并且这个角色决定发起连接的命令的初始访问权限。要使用一个特定数据库连接的角色名由客户端指示,该客户端以一种应用相关的风格发起连接请求。例如,psql程序使用-U命令行选项来指定要以哪个角色连接。很多应用假定该名字默认是当前操作系统用户(包括createuser和psql)。因此在角色和操作系统用户之间维护一个名字对应关系通常是很方便的。</p>
</div>
<div class="paragraph">
<p>一个给定客户端连接能够用来连接的数据库角色的集合由该客户端的认证设置决定,因此,一个客户端不止限于以匹配其操作系统用户的角色连接,就像一个人的登录名不需要匹配她的真实名字一样。因为角色身份决定一个已连接客户端可用的权限集合,在设置一个多用户环境时要小心地配置权限。</p>
</div>
<div class="paragraph">
<p>一个数据库角色可以有一些属性,它们定义角色的权限并且与客户端认证系统交互。</p>
</div>
<div class="paragraph">
<p>把用户分组在一起来便于管理权限常常很方便:那样,权限可以被授予一整个组或从一整个组回收。在IvorySQL中通过创建一个表示组的角色来实现,并且然后将在该组角色中的 <strong>成员关系</strong> 授予给单独的用户角色。</p>
</div>
<div class="paragraph">
<p>由于角色可以拥有数据库对象并且能持有访问其他对象的特权,删除一个角色常常并非一次DROP ROLE就能解决。 任何被该用户所拥有的对象必须首先被删除或者转移给其他拥有者,并且任何已被授予给该角色的权限必须被收回。</p>
</div>
<div class="paragraph">
<p>更多有关数据库访问管理的细节,可以参阅 <a href="https://www.postgresql.org/docs/17/user-manag.html">手册</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="定义数据对象"><a class="anchor" href="#定义数据对象"></a>4. 定义数据对象</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IvorySQL基于PostgreSQL,具有完整的SQL,其定义数据对象可以参考 <a href="https://www.postgresql.org/docs/current/ddl.html">手册</a>。在此基础之上,IvorySQL为兼容Oracle,还做了一些Oracle专有数据对象的兼容。</p>
</div>
<div class="sect2">
<h3 id="varchar2"><a class="anchor" href="#varchar2"></a>4.1. VARCHAR2</h3>
<div class="sect3">
<h4 id="概述"><a class="anchor" href="#概述"></a>4.1.1. 概述</h4>
<div class="paragraph">
<p>具有最大长度大小字节或字符的可变长度字符串。 您必须为 VARCHAR2 指定大小。 最小大小为 1 个字节或 1 个字符。</p>
</div>
</div>
<div class="sect3">
<h4 id="语法"><a class="anchor" href="#语法"></a>4.1.2. 语法</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">VARCHAR2(size)</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="用例"><a class="anchor" href="#用例"></a>4.1.3. 用例</h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">create table test(a varchar2(5));
CREATE TABLE
SET NLS_LENGTH_SEMANTICS TO CHAR;
SET
SHOW NLS_LENGTH_SEMANTICS;
nls_length_semantics
----------------------
char
(1 row)
insert into test values ('李老师您好');
INSERT 0 1</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="查询数据"><a class="anchor" href="#查询数据"></a>5. 查询数据</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IvorySQL基于PostgreSQL开发,具有完全的SQL,查询数据具体的操作可以参考 <a href="https://www.postgresql.org/docs/current/queries.html">手册</a>。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="使用外部数据"><a class="anchor" href="#使用外部数据"></a>6. 使用外部数据</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IvorySQL实现了部分的SQL/MED规定,允许我们使用普通SQL查询来访问位于IvorySQL之外的数据。这种数据被称为外部数据(注意这种用法不要和外键混淆,后者是数据库中的一种约束)。</p>
</div>
<div class="paragraph">
<p>外部数据可以在一个外部数据包装器的帮助下被访问。一个外部数据包装器是一个库,它可以与一个外部数据源通讯,并隐藏连接到数据源和从它获取数据的细节。在contrib模块中有一些外部数据包装器,参见 <a href="https://www.postgresql.org/docs/current/contrib.html">文档</a>。其他类型的外部数据包装器可以在第三方产品中找到。如果这些现有的外部数据包装器都不能满足你的需要,可以自己编写一个,参见 <a href="https://www.postgresql.org/docs/current/fdwhandler.html">手册</a>。</p>
</div>
<div class="paragraph">
<p>要访问外部数据,我们需要建立一个外部服务器对象,它根据它所支持的外部数据包装器所使用的一组选项定义了如何连接到一个特定的外部数据源。接着我们需要创建一个或多个外部表,它们定义了外部数据的结构。一个外部表可以在查询中像一个普通表一样地使用,但是在IvorySQL服务器中外部表没有存储数据。不管使用什么外部数据包装器,IvorySQL会要求外部数据包装器从外部数据源获取数据,或者在更新命令的情况下传送数据到外部数据源。</p>
</div>
<div class="paragraph">
<p>访问远程数据可能需要在外部数据源的授权。这些信息通过一个用户映射提供,它基于当前的IvorySQL角色提供了附加的数据例如用户名和密码。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="备份与恢复"><a class="anchor" href="#备份与恢复"></a>7. 备份与恢复</h2>
<div class="sectionbody">
<div class="paragraph">
<p>由于包含着有价值的数据,IvorySQL数据库应当被定期地备份。虽然过程相当简单,但清晰地理解其底层技术和假设是非常重要的。</p>
</div>
<div class="paragraph">
<p>有三种不同的基本方法来备份 IvorySQL 数据:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>SQL转储</p>
</li>
<li>
<p>文件系统级备份</p>
</li>
<li>
<p>连续归档</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="sql转储"><a class="anchor" href="#sql转储"></a>7.1. SQL转储</h3>
<div class="paragraph">
<p>SQL 转储方法的思想是创建一个由SQL命令组成的文件,当把这个文件回馈给服务器时,服务器将利用其中的SQL命令重建与转储时状态一样的数据库。 IvorySQL为此提供了工具pg_dump。这个工具的基本用法是:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump dbname > dumpfile</code></pre>
</div>
</div>
<div class="paragraph">
<p>正如你所见,pg_dump把结果输出到标准输出。我们后面将看到这样做有什么用处。 尽管上述命令会创建一个文本文件,pg_dump可以用其他格式创建文件以支持并行 和细粒度的对象恢复控制。</p>
</div>
<div class="paragraph">
<p> pg_dump是一个普通的IvorySQL客户端应用(尽管是个 相当聪明的东西)。这就意味着你可以在任何可以访问该数据库的远端主机上进行备份工作。但是请记住 pg_dump不会以任何特殊权限运行。具体说来,就是它必须要有你想备份的表的读权限,因此为了备份整个数据库你几乎总是必须以一个数据库超级用户来运行它(如果你没有足够的特权来备份整个数据库,你仍然可以使用诸如-n schema 或-t table选项来备份该数据库中你能够访问的部分)。</p>
</div>
<div class="paragraph">
<p> 要声明pg_dump连接哪个数据库服务器,使用命令行选项-h host和 -p port。 默认主机是本地主机或你的HOST环境变量指定的主机。 类似地,默认端口是环境变量PORT或(如果PORT不存在)内建的默认值。 (服务器通常有相同的默认值,所以还算方便。)</p>
</div>
<div class="paragraph">
<p> pg_dump默认使用与当前操作系统用户名同名的数据库用户名进行连接。 要使用其他名字,要么声明-U选项,要么设置环境变量PGUSER。请注意pg_dump的连接也要通过客户认证机制。</p>
</div>
<div class="paragraph">
<p> pg_dump对于其他备份方法的一个重要优势是,pg_dump的输出可以很容易地在新版本的IvorySQL中载入,而文件级备份和连续归档都是极度的服务器版本限定的。pg_dump也是唯一可以将一个数据库传送到一个不同机器架构上的方法,例如从一个32位服务器到一个64位服务器。</p>
</div>
<div class="paragraph">
<p> 由pg_dump创建的备份在内部是一致的, 也就是说,转储表现了pg_dump开始运行时刻的数据库快照,且在pg_dump运行过程中发生的更新将不会被转储。pg_dump工作的时候并不阻塞其他的对数据库的操作。(但是会阻塞那些需要排它锁的操作,比如大部分形式的ALTER TABLE)</p>
</div>
<div class="sect3">
<h4 id="从转储中恢复"><a class="anchor" href="#从转储中恢复"></a>7.1.1. 从转储中恢复</h4>
<div class="paragraph">
<p>pg_dump生成的文本文件可以由psql程序读取。 从转储中恢复的常用命令是:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">psql dbname < dumpfile</code></pre>
</div>
</div>
<div class="paragraph">
<p>其中dumpfile就是pg_dump命令的输出文件。这条命令不会创建数据库dbname,你必须在执行psql前自己从template0创建(例如,用命令createdb -T template0 dbname)。psql支持类似pg_dump的选项用以指定要连接的数据库服务器和要使用的用户名。参阅psql的手册获取更多信息。 非文本文件转储可以使用pg_restore工具来恢复。</p>
</div>
<div class="paragraph">
<p> 在开始恢复之前,转储库中对象的拥有者以及在其上被授予了权限的用户必须已经存在。如果它们不存在,那么恢复过程将无法将对象创建成具有原来的所属关系以及权限(有时候这就是你所需要的,但通常不是)。</p>
</div>
<div class="paragraph">
<p> 默认情况下,psql脚本在遇到一个SQL错误后会继续执行。你也许希望在遇到一个SQL错误后让psql退出,那么可以设置ON_ERROR_STOP变量来运行psql,这将使psql在遇到SQL错误后退出并返回状态3:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">psql --set ON_ERROR_STOP=on dbname < infile</code></pre>
</div>
</div>
<div class="paragraph">
<p>不管怎样,你将只能得到一个部分恢复的数据库。作为另一种选择,你可以指定让整个恢复作为一个单独的事务运行,这样恢复要么完全完成要么完全回滚。这种模式可以通过向psql传递-1或—​single-transaction命令行选项来指定。在使用这种模式时,注意即使是很小的一个错误也会导致运行了数小时的恢复被回滚。但是,这仍然比在一个部分恢复后手工清理复杂的数据库要更好。</p>
</div>
<div class="paragraph">
<p> pg_dump和psql读写管道的能力使得直接从一个服务器转储一个数据库到另一个服务器成为可能,例如:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump -h host1 dbname | psql -h host2 dbname</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>重要:</strong>pg_dump产生的转储是相对于template0。这意味着在template1中加入的任何语言、过程等都会被pg_dump转储。结果是,如果在恢复时使用的是一个自定义的template1,你必须从template0创建一个空的数据库,正如上面的例子所示。</p>
</div>
<div class="paragraph">
<p> 一旦完成恢复,在每个数据库上运行ANALYZE是明智的举动,这样优化器就有有用的统计数据了。</p>
</div>
</div>
<div class="sect3">
<h4 id="使用pg_dumpall"><a class="anchor" href="#使用pg_dumpall"></a>7.1.2. 使用pg_dumpall</h4>
<div class="paragraph">
<p>pg_dump每次只转储一个数据库,而且它不会转储关于角色或表空间(因为它们是集簇范围的)的信息。为了支持方便地转储一个数据库集簇的全部内容,提供了pg_dumpall程序。pg_dumpall备份一个给定集簇中的每一个数据库,并且也保留了集簇范围的数据,如角色和表空间定义。该命令的基本用法是:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dumpall > dumpfile</code></pre>
</div>
</div>
<div class="paragraph">
<p>转储的结果可以使用psql恢复:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">psql -f dumpfile postgres</code></pre>
</div>
</div>
<div class="paragraph">
<p>(实际上,你可以指定恢复到任何已有数据库名,但是如果你正在将转储载入到一个空集簇中则通常要用(postgres)。在恢复一个pg_dumpall转储时常常需要具有数据库超级用户访问权限,因为它需要恢复角色和表空间信息。如果你在使用表空间,请确保转储中的表空间路径适合于新的安装。</p>
</div>
<div class="paragraph">
<p>pg_dumpall工作时会发出命令重新创建角色、表空间和空数据库,接着为每一个数据库pg_dump。这意味着每个数据库自身是一致的,但是不同数据库的快照并不同步。</p>
</div>
<div class="paragraph">
<p>集簇范围的数据可以使用pg_dumpall的—​globals-only选项来单独转储。如果在单个数据库上运行pg_dump命令,上述做法对于完全备份整个集簇是必需的。</p>
</div>
</div>
<div class="sect3">
<h4 id="处理大型数据库"><a class="anchor" href="#处理大型数据库"></a>7.1.3. 处理大型数据库</h4>
<div class="paragraph">
<p>在一些具有最大文件尺寸限制的操作系统上创建大型的pg_dump输出文件可能会出现问题。幸运地是,pg_dump可以写出到标准输出,因此你可以使用标准Unix工具来处理这种潜在的问题。有几种可能的方法:</p>
</div>
<div class="paragraph">
<p>使用压缩转储。你可以使用你喜欢的压缩程序,例如gzip:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump dbname | gzip > filename.gz</code></pre>
</div>
</div>
<div class="paragraph">
<p>恢复:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">gunzip -c filename.gz | psql dbname</code></pre>
</div>
</div>
<div class="paragraph">
<p>或者:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">cat filename.gz | gunzip | psql dbname</code></pre>
</div>
</div>
<div class="paragraph">
<p>使用split。split命令允许你将输出分割成较小的文件以便能够适应底层文件系统的尺寸要求。例如,让每一块的大小为2G字节:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump dbname | split -b 2G - filename</code></pre>
</div>
</div>
<div class="paragraph">
<p>恢复:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">cat filename* | psql dbname</code></pre>
</div>
</div>
<div class="paragraph">
<p>如果使用GNU split,可能会把它和gzip一起使用:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump dbname | split -b 2G -−filter='gzip > $FILE.gz'</code></pre>
</div>
</div>
<div class="paragraph">
<p>它可以使用zcat恢复。</p>
</div>
<div class="paragraph">
<p>使用pg_dump的自定义转储格式。. 如果 IvorySQL 所在的系统上安装了zlib压缩库,自定义转储格式将在写出数据到输出文件时对其压缩。这将产生和使用gzip时差不多大小的转储文件,但是这种方式的一个优势是其中的表可以被有选择地恢复。下面的命令使用自定义转储格式来转储一个数据库:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump -Fc dbname > filename</code></pre>
</div>
</div>
<div class="paragraph">
<p>自定义格式的转储不是psql的脚本,只能通过pg_restore恢复,例如:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_restore -d dbname filename</code></pre>
</div>
</div>
<div class="paragraph">
<p>更多细节可以参阅 <a href="https://www.postgresql.org/docs/17/reference-client.html">手册</a>。</p>
</div>
<div class="paragraph">
<p>对于非常大型的数据库,你可能需要将split配合其他两种方法之一进行使用。</p>
</div>
<div class="paragraph">
<p>使用pg_dump的并行转储特性。 为了加快转储一个大型数据库的速度,你可以使用pg_dump的并行模式。它将同时转储多个表。你可以使用-j参数控制并行度。并行转储只支持“目录”归档格式。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">pg_dump -j num -F d -f out.dir dbname</code></pre>
</div>
</div>
<div class="paragraph">
<p>你可以使用pg_restore -j来以并行方式恢复一个转储。它只能适合于“自定义”归档或者“目录”归档,但不管归档是否由pg_dump -j创建。</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="文件系统级别备份"><a class="anchor" href="#文件系统级别备份"></a>7.2. 文件系统级别备份</h3>
<div class="paragraph">
<p>另外一种备份策略是直接复制 IvorySQL用于存储数据库中数据的文件,你可以采用任何你喜欢的方式进行文件系统备份,例如:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">tar -cf backup.tar /usr/local/pgsql/data</code></pre>
</div>
</div>
<div class="paragraph">
<p>但是这种方法有两个限制,使得这种方法不实用,或者说至少比pg_dump方法差:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>为了得到一个可用的备份,数据库服务器必须被关闭。例如阻止所有连接的半路措施是不起作用的(部分原因是tar和类似工具无法得到文件系统状态的一个原子的快照,还有服务器内部缓冲的原因)。不用说,在恢复数据之前你也需要关闭服务器。</p>
</li>
<li>
<p>如果你已经深入地了解了数据库的文件系统布局的细节,你可能会有兴趣尝试通过相应的文件或目录来备份或恢复特定的表或数据库。这种方法也不会起作用,因为包含在这些文件中的信息只有配合提交日志文件(pg_xact/*)才有用,提交日志文件包含了所有事务的提交状态。一个表文件只有和这些信息一起才有用。当然也不可能只恢复一个表及相关的pg_xact数据,因为这会导致数据库集簇中所有其他表变得无用。因此文件系统备份值适合于完整地备份或恢复整个数据库集簇。</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>另一种文件系统备份方法是创建一个数据目录的“一致快照”,如果文件系统支持此功能(并且你相信它的实现正确)。典型的过程是创建一个包含数据库的卷的“冻结快照”,然后从该快照复制整个数据目录(如上,不能是部分复制)到备份设备,最后释放冻结快照。即使在数据库服务器运行时,这种方式也有效。但是,以这种方式创建的备份保存的文件看起来就像数据库没有被正确关闭时的状态。因此,当你从备份数据上启动数据库服务器时,它会认为上一次的服务器实例崩溃了并尝试重放WAL日志。这不是问题,只是需要注意(当然WAL文件必须要包括在备份中)。你可以在拍摄快照之前执行一次CHECKPOINT以便节省恢复时间。</p>
</div>
<div class="paragraph">
<p>如果你的数据库跨越多个文件系统,可能没有任何方式可以对所有卷获得完全同步的冻结快照。例如,如果你的数据文件和WAL日志放置在不同的磁盘上,或者表空间在不同的文件系统中,可能没有办法使用快照备份,因为快照必须是同步的。在这些情况下,一定要仔细阅读你的文件系统文档以了解其对一致快照技术的支持。</p>
</div>
<div class="paragraph">
<p>如果没有可能获得同步快照,一种选择是将数据库服务器关闭足够长的时间以建立所有的冻结快照。另一种选择是执行一次连续归档基础备份,因为这种备份对于备份期间发生的文件系统改变是免疫的。这要求在备份过程中允许连续归档,恢复时使用连续归档恢复。</p>
</div>
<div class="paragraph">
<p>还有一种选择是使用rsync来执行一次文件系统备份。其做法是先在数据库服务器运行时执行rsync,然后关闭数据库服务器足够长时间来做一次rsync --checksum (--checksum是必需的,因为rsync的文件修改 时间粒度只能精确到秒)。第二次rsync会比第一次快,因为它只需要传送相对很少的数据,由于服务器是停止的,所以最终结果将是一致的。这种方法允许在最小停机时间内执行一次文件系统备份。</p>
</div>
<div class="paragraph">
<p>注意一个文件系统备份通常会比一个SQL转储体积更大(例如pg_dump不需要转储索引的内容,而是转储用于重建索引的命令)。但是,做一次文件系统备份可能更快。</p>
</div>
</div>
<div class="sect2">
<h3 id="连续归档和时间点恢复pitr"><a class="anchor" href="#连续归档和时间点恢复pitr"></a>7.3. 连续归档和时间点恢复(PITR)</h3>
<div class="paragraph">
<p>在任何时间,IvorySQL在数据集簇目录的pg_wal/子目录下都保持有一个预写式日志(WAL)。这个日志存在的目的是为了保证崩溃后的安全:如果系统崩溃,可以“重放”从最后一次检查点以来的日志项来恢复数据库的一致性。该日志的存在也使得第三种备份数据库的策略变得可能:我们可以把一个文件系统级别的备份和WAL文件的备份结合起来。当需要恢复时,我们先恢复文件系统备份,然后从备份的WAL文件中重放来把系统带到一个当前状态。这种方法比之前的方法管理起来要更复杂,但是有其显著的优点:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>我们不需要一个完美的一致的文件系统备份作为开始点。备份中的任何内部不一致性将通过日志重放(这和崩溃恢复期间发生的并无显著不同)来修正。因此我们不需要文件系统快照功能,只需要tar或一个类似的归档工具。</p>
</li>
<li>
<p>由于我们可以结合一个无穷长的WAL文件序列用于重放,可以通过简单地归档WAL文件来达到连续备份。这对于大型数据库特别有用,因为在其中不方便频繁地进行完全备份。</p>
</li>
<li>
<p>并不需要一直重放WAL项一直到最后。我们可以在任何点停止重放,并得到一个数据库在当时的一致快照。这样,该技术支持时间点恢复: 在得到你的基础备份以后,可以将数据库恢复到它在其后任何时间的状态。</p>
</li>
<li>
<p>如果我们连续地将一系列WAL文件输送给另一台已经载入了相同基础备份文件的机器, 我们就得到了一个热后备系统: 在任何时间点我们都能提出第二台机器, 它差不多是数据库的当前副本。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>注意:</strong> pg_dump 和 pg_dumpall不会产生文件系统级别的备份,并且不能用于连续归档方案。这类转换是逻辑的并且不包含足够的信息用于WAL重放。</p>
</div>
<div class="paragraph">
<p> 就简单的文件系统备份技术来说,这种方法只能支持整个数据库集簇的恢复,却无法支持其中一个子集的恢复。另外,它需要大量的归档存储:一个基础备份的体积可能很庞大,并且一个繁忙的系统将会产生大量需要被归档的WAL流量。尽管如此,在很多需要高可靠性的情况下,它是首选的备份技术。</p>
</div>
<div class="paragraph">
<p> 要使用连续归档(也被很多数据库厂商称为“在线备份”)成功地恢复,你需要一个从基础备份时间开始的连续的归档WAL文件序列。为了开始,在你建立第一个基础备份之前,你应该建立并测试用于归档WAL文件的过程。对应地,我们首先讨论归档WAL文件的机制。关于如何建立归档和备份的方式以及操作过程中的要点,请参阅 <a href="https://www.postgresql.org/docs/17/backup.html">手册</a>。</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="装卸数据"><a class="anchor" href="#装卸数据"></a>8. 装卸数据</h2>
<div class="sectionbody">
<div class="paragraph">
<p>copy 在 IvorySQL表和标准文件之间移动数据。COPY TO 把一个表的内容复制到一个文件,而COPY FROM 则从一个文件复制数据到一个表(把数据追加到表中原有数据)。COPY TO 也能复制一个SELECT查询的结果。</p>
</div>
<div class="paragraph">
<p> 如果指定了一个列列表,COPY TO将只把指定列的数据复制到文件。对于COPY FROM,文件中的每个字段将按顺序插入到指定列中。COPY FROM命令的列列表中没有指定的表列则会采纳其默认值。</p>
</div>
<div class="paragraph">
<p> 带一个文件名的COPY指示IvorySQL服务器直接从一个文件读取或者写入到一个文件。该文件必须是IvorySQL用户(运行服务器的用户ID)可访问的并且应该以服务器的视角来指定其名称。当指定了PROGRAM时,服务器执行给定的命令并且从该程序的标准输出读取或者写入到该程序的标准输入。该程序必须以服务器的视角指定,并且必须是IvorySQL用户可执行的。在指定STDIN或者STDOUT时,数据会通过客户端和服务器之间的连接传输。</p>
</div>
<div class="paragraph">
<p> 运行COPY的每个后端将在pg_stat_progress_copy视图中报告其进度。</p>
</div>
<div class="sect2">
<h3 id="大纲"><a class="anchor" href="#大纲"></a>8.1. 大纲</h3>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | PROGRAM 'command' | STDIN }
[ [ WITH ] ( option [, ...] ) ]
[ WHERE condition ]
COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
TO { 'filename' | PROGRAM 'command' | STDOUT }
[ [ WITH ] ( option [, ...] ) ]
其中 option 可以是下列之一:
FORMAT format_name
FREEZE [ boolean ]
DELIMITER 'delimiter_character'
NULL 'null_string'
HEADER [ boolean ]
QUOTE 'quote_character'
ESCAPE 'escape_character'
FORCE_QUOTE { ( column_name [, ...] ) | * }
FORCE_NOT_NULL ( column_name [, ...] )
FORCE_NULL ( column_name [, ...] )
ENCODING 'encoding_name'</code></pre>
</div>
</div>
<div class="paragraph">
<p>详细参数设置,请参阅 <a href="https://www.postgresql.org/docs/17/sql-copy.html">手册</a>。</p>
</div>
</div>
<div class="sect2">
<h3 id="输出"><a class="anchor" href="#输出"></a>8.2. 输出</h3>
<div class="paragraph">
<p>在成功完成时,一个COPY命令会返回一个形为</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-asciidoc hljs" data-lang="asciidoc">COPY count</code></pre>
</div>
</div>