HA (high availability) là một cấu trúc hệ thống không thể thiếu trong vận hành một database system. Bài viết này sẽ giới thiệu cách cấu hình một PostgreSQL cluster sử dụng pacemaker và DRDB.
Pacemaker
Pacemaker là một phần mềm mã nguồn mở dùng để quản lý HA cluster được sử dụng rất phổ biến trong các hệ thống hạ tầng IT.
Đặc điểm của pacemaker
Pacemaker được cấu thành từ 2 bộ phận chính corosync và pacemaker. Corosync thực hiện giám sát, giao tiếp giữa các node trong cluster, trong khi pacemaker quản lý điều khiển các hoạt động của resource agents trong cluster. Resource agents là những agent được viết dưới dạng script (bash, perl, ..) xử lý giám sát các resource (như volume, VIP, filesystem,..) và được điều khiển bởi pacemaker.
Về tổng quan, pacemaker nổi bật với những tính năng bên dưới.
- Giám sát hệ thống và tự động phục hồi service khi có lỗi
- Hỗ trợ nhiều servers trong cùng một cluster
- Tính sử dụng cao (nhờ có thể chỉnh sửa resource agent)
DRBD (Distributed Replicated Block Device)
DRBD là một phần mềm phát triển bởi linbit dùng để đồng bộ dữ liệu giữa 2 node ở mức độ block dữ liệu. drbd được sử dụng phổ biến trong những hệ thống đơn giản và dữ liệu đồng bộ không lớn lắm. Một số đặc điểm về drbd.
- Thiết lập ban đầu đơn giản
- Dễ dàng kết hợp với cluster như pacemaker
- Không cần hiệu chỉnh nhiều trong lúc vận hành
Ngoài những ưu điểm trên, DRBD khó vận hành khi replicate nhiều nodes (ở phiên bản trước 9.0, DRBD chỉ cho phép replicate giữa 2 nodes)
- drbd chỉ cho phép đồng bộ dữ liệu giữa 2 node.
- đồng bộ toàn bộ (drbd volume) dữ liệu khi split brain xảy ra.
Ở một số phương pháp đồng bộ khác như rsync, chỉ cần đồng bộ những files có thay đổi. Như vậy sẽ giảm thiểu nhiều thời gian đồng bộ dữ liệu từ primary node. Thời gian phục hồi secondary node ảnh hưởng tới tính HA của hệ thống.
Cấu hình
Bên dưới mình trình bày một hướng dẫn cụ thể cấu hình một PostgreSQL cluster sử dụng pacemaker và DRBD.
Môi trường thực thi
# | Resources | phiên bản | Ghi Chú |
---|
1 | OS | CentOS 8 | Bao gồm 2 nodes, node1: 172.17.28.69 và node2: 172.17.28.71 |
2 | PostgreSQL | 13 beta 2 | sử dụng bản build từ source |
3 | Pacemaker | Sử dụng package từ CentOS yum repo | Sử dụng rerource agents: drbd, Filesystem, pgsql, IP |
4 | DRBD | 9.0 | sử dụng giao thức (mức độ đồng bộ) B (đồng bộ trên memory hay tiền đồng bộ). Bài viết này mình cấu hình DRBD trên LVM (phần mềm quản lý volume logic được sử dụng rất phổ biến. |
Các bước thực hiện
Cài đặt PostgreSQL 13 beta2 Thực hiện trên: 2 nodes
Đã có nhiều bài viết liên quan tới cài đặt nên ở đây mình sẽ giảm thiểu giải thích các bước cài đặt PostgreSQL
# cd /usr/local/src
# wget https://ftp.postgresql.org/pub/source/v13beta2/postgresql-13beta2.tar.gz > /dev/null
# tar xfz postgresql-13beta2.tar.gz
# cd postgresql-13beta2
# ./configure --prefix=/usr/local/pgsql/pg13 > /dev/null
# make -j16 install > /dev/null
Cấu hình LVM và DRBD
Thực hiện trên: 2 nodes
Download drbd packages
Download DRBD packages từ đây
+ drbd90-utils-9.13.1-1.el8.elrepo.x86_64.rpm
+ drbd90-utils-sysvinit-9.13.1-1.el8.elrepo.x86_64.rpm
+ kmod-drbd90-9.0.23-1.el8_2.elrepo.x86_64.rpm
Thực hiện trên: 2 nodes
Cài đặt drbd packages
sudo yum localinstall *rpm
Thực hiện trên: 2 nodes
Kiểm tra xem firewalld đã tắt chưa
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Docs: man:firewalld(1)
Tắt Firewalld ở đây để thuận lợi khi giao tiếp giữa các nodes. Nếu firewalld chưa tắt, bạn có thể tắt và vô hiệu hóa bằng lệnh systemctl stop firewalld; systemctl disable firewalld
.
Thực hiện trên: 2 nodes
Tạo ổ đĩa logic LVM
Thông tin thiết lập LVM
# | Resources | phiên bản |
---|
1 | Tên ổ đĩa | /dev/sdb |
2 | Tên physical volume | /dev/sdb1 |
3 | Tên volume group | vg |
4 | Tên logical volume | lv |
Ở đây mình chuẩn bị một đĩa cứng với dung lượng 1GB (sdb) và chỉ sử dụng 512MB cho DRBD volume.
# fdisk /dev/sdb
...snip...
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (1-4, default 1):
First sector (2048-2097151, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-2097151, default 2097151):
Created a new partition 1 of type 'Linux' and of size 1023 MiB.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 15G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 14G 0 part
├─cl-root 253:0 0 12.5G 0 lvm /
└─cl-swap 253:1 0 1.5G 0 lvm [SWAP]
sdb 8:16 0 1G 0 disk
└─sdb1 8:17 0 1023M 0 part
sr0 11:0 1 7.7G 0 rom
# pvcreate /dev/sdb1
Physical volume "/dev/sdb1" successfully created.
# vgcreate vg /dev/sdb1
Volume group "vg" successfully created
# lvcreate --size 512MB --name lv vg
Logical volume "lv" created.
#
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 15G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 14G 0 part
├─cl-root 253:0 0 12.5G 0 lvm /
└─cl-swap 253:1 0 1.5G 0 lvm [SWAP]
sdb 8:16 0 1G 0 disk
└─sdb1 8:17 0 1023M 0 part
└─vg-lv 253:2 0 512M 0 lvm
sr0 11:0 1 7.7G 0 rom
[root@node1 src]#
- Tạo ổ đĩa DRBD trên LVM đã tạo
Thông tin thiết lập ổ DRBD
# | Nội dung | giải thích |
---|
1 | Tên LVM sử dụng cho DRBD | /dev/vg/lv |
2 | Node1 IP | 172.17.28.69 |
3 | Node2 IP | 172.17.28.71 |
4 | Port sử dụng cho replicate dữ liệu | 7001 |
5 | Protocol | B (đồng bộ mức độ bộ nhớ) |
Thực hiện trên: 2 nodes
Tạo file drbd resource
# vi /etc/drbd.d/pgres.res
resource pgres {
protocol B;
device minor 1;
meta-disk internal;
disk /dev/mapper/vg-lv;
on node1 {
address 172.17.28.69:7001;
}
on node2 {
address 172.17.28.71:7001;
}
}
Bạn có thể thao khảo thêm ở manual của DRBD để có thêm nhiều tinh chỉnh.
Thực hiện trên: 2 nodes
Tạo meta data cho ổ DRBD
# drbdadm create-md pgres
initializing activity log
initializing bitmap (16 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.
#
Thực hiện trên: 2 nodes
Khởi động DRBD
# systemctl start drbd
# systemctl enable drbd
Synchronizing state of drbd.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable drbd
Created symlink /etc/systemd/system/multi-user.target.wants/drbd.service → /usr/lib/systemd/system/drbd.service.
# drbdadm status pgres
pgres role:Secondary
disk:Inconsistent
node2 role:Secondary
peer-disk:Inconsistent
Thực hiện trên: Node1
Thiết lập node 1 là primary
[root@node1 ~]# drbdadm --force primary pgres
[root@node1 ~]# drbdadm status pgres
pgres role:Primary
disk:UpToDate
node2 role:Secondary
peer-disk:UpToDate
[root@node1 ~]##
Thực hiện trên: Node1
Định dạng xfs cho ổ DRBD
[root@node1 src]# mkfs.xfs /dev/drbd1 -L PGDATA -f
meta-data=/dev/drbd1 isize=512 agcount=4, agsize=32765 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=131059, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=1368, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@node1 src]#
Tới đây mình có thể sử dụng ổ drbd, dữ liệu sẽ được đồng bộ từ node primary sang secondary. Bạn có thể chuyển chuyển vai trò các nodes lẫn nhau nhờ lệnh drbd secondary pgres
để chuyển vai trò ổ drbd sang secondary (passive) drbd primary pgres
để chuyển vai trò thành primary (active)
Cài đặt Pacemaker
Phần này mình sẽ hướng dẫn cài đặt pacemaker với cấu trúc như bên dưới.
+ [ VIP: 172.17.28.111 ] (resources: drbd, Filesystem, pgsql, Ip)
+ |
++----------------------+ | +----------------------+
+| [ Cluster Node1 ] | | | [ Cluster Node2 ] |
+| IP: 172.17.28.69 +----------+----------+ 172.17.28.71 |
+| | | |
++----------------------+ +----------------------+
Các giá trị thiết lập cho pacemaker resources.
# | Resource | giá trị | Chú thích |
---|
1 | ocf:linbit:drbd | drbd_resource=pgres | Sử dụng pgres resource vừa tạo |
2 | ocf:heartbeat:Filesystem | device="/dev/drbd1" directory=/pgdata fstype=xfs | Mount ổ DRBD vào thư mục dữ liệu |
3 | ocf:heartbeat:pgsql | pgctl=/usr/local/pgsql/pg13/bin/pg_ctl psql=/usr/local/pgsql/pg13/bin/psql pgdata=/pgdata/pg13data pgport=5432 | PostgreSQL resource. Thực hiện các thao tác khởi động, monitoring, ... PostgreSQL. |
4 | ocf:heartbeat:IPaddr2 | ip=172.17.28.111 | VIP resource. Thực hiện các thao tác khởi động mornitoring, ... IP ảo cho cluster. |
Các bước thực hiện với pacemaker
Thực hiện trên: 2 Nodes
thực hiện enable HighAvailability yum repo (mặc định repo này không được enable trên CentOS 8), và cài đặt pacemaker packages.
# dnf config-manager --set-enabled HighAvailability
# yum install -y pacemaker pcs fence-agents-all psmisc > /dev/null
Thực hiện trên: 2 Nodes
Thiết lập mật khẩu cho hacluster OS user (user này được tạo ra khi cài đặt pacemaker packages).
# echo "firstclt" | sudo passwd hacluster --stdin
Changing password for user hacluster.
passwd: all authentication tokens updated successfully.
Thực hiện trên: 2 Nodes
Khởi động pcsd deamon (để có thể thực hiện các câu lệnh pcs).
# sudo systemctl start pcsd.service
# systemctl enable pcsd.service
Created symlink /etc/systemd/system/multi-user.target.wants/pcsd.service → /usr/lib/systemd/system/pcsd.service.
Thực hiện trên: 2 Nodes
Thực hiện chứng thực giữa các nodes cho cluster
# sudo pcs host auth node1 node2 -u hacluster -p firstclt
node2: Authorized
node1: Authorized
Thực hiện trên: Node1
Khởi tạo cluster và khởi động
[root@node1 ~]# sudo pcs cluster setup firstcluster node1 node2 --force --start
...snip...
Sending 'corosync authkey', 'pacemaker authkey' to 'node1', 'node2'
node2: successful distribution of the file 'corosync authkey'
node2: successful distribution of the file 'pacemaker authkey'
node1: successful distribution of the file 'corosync authkey'
node1: successful distribution of the file 'pacemaker authkey'
Sending 'corosync.conf' to 'node1', 'node2'
node2: successful distribution of the file 'corosync.conf'
node1: successful distribution of the file 'corosync.conf'
Cluster has been successfully set up.
Starting cluster on hosts: 'node1', 'node2'...
[root@node1 ~]#
- Xác nhận trạng thái cluster
# crm_mon -Arf1
Cluster Summary:
* Stack: corosync
* Current DC: node1 (version 2.0.3-5.el8_2.1-4b1f869f0f) - partition with quorum
* Last updated: Wed Jul 15 03:29:57 2020
* Last change: Wed Jul 15 03:29:48 2020 by hacluster via crmd on node1
* 2 nodes configured
* 0 resource instances configured
Node List:
* Online: [ node1 node2 ]
Full List of Resources:
* No resources
Migration Summary:
Thực hiện trên: Node1
Thiết lập một số thông số mặc định
[root@node1 ~]# pcs cluster enable --all # thiết lập khởi động cluster cùng với OS
[root@node1 ~]# pcs property set stonith-enabled=false # không thiết lập snonith vì không có device liên quan
[root@node1 ~]# pcs property set cluster-recheck-interval=10m # kiểm tra trạng thái mỗi 10 phút
[root@node1 ~]# pcs property set no-quorum-policy=ignore # thiết lập thao tác khi mất quorum
Thực hiện trên: Node1
Tạo DRBD resource trên cluster
# pcs resource create drbd-fisrtcluster ocf:linbit:drbd drbd_resource=pgres op monitor \
interval=15s op start timeout=60 op stop timeout=60 op promote timeout=90
# pcs resource promotable drbd-fisrtcluster master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true
# pcs resource cleanup
Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
* Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
* Masters: [ node1 ]
* Slaves: [ node2 ]
...snip...
Thực hiện trên: Node1
Tạo Filesystem resource trên cluster
# sudo mkdir /pgdata # tạo data directory để mount filesystem
# sudo pcs resource create pgFS-firstcluster ocf:heartbeat:Filesystem device="/dev/drbd1" \
directory=/pgdata fstype=xfs options=defaults,noatime,nodiratime,attr2 op start timeout=60 \
op stop timeout=60 --group masterg-firstcluster
- Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
* Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
* Masters: [ node1 ]
* Slaves: [ node2 ]
* Resource Group: masterg-firstcluster:
* pgFS-firstcluster (ocf::heartbeat:Filesystem): Started node1
...snip...
Thực hiện trên: Node1
Khởi tạo postgres DB cluster trên filesystem vừa tạo
[root@node1 ~]# chown postgres /pgdata/ -R
[root@node1 ~]# df -h /pgdata
Filesystem Size Used Avail Use% Mounted on
/dev/drbd1 507M 30M 478M 6% /pgdata
[root@node1 ~]# su - postgres
$ /usr/local/pgsql/pg13/bin/initdb -E utf8 --no-locale -D /pgdata/pg13data
Thực hiện trên: Node1
Tạo pgsql resource cho postgres
# sudo pcs resource create pgsql-firstcluster ocf:heartbeat:pgsql \
pgctl=/usr/local/pgsql/pg13/bin/pg_ctl psql=/usr/local/pgsql/pg13/bin/psql \
pgdata=/pgdata/pg13data pgport=5432 stop_escalate=1 op start timeout=60s \
interval=0s on-fail=restart op monitor timeout=60s interval=7s on-fail=restart \
op monitor timeout=60s interval=2s on-fail=restart role=Master op promote \
timeout=60s interval=0s on-fail=restart op demote timeout=60s interval=0s \
on-fail=stop op stop timeout=60s interval=0s on-fail=block op notify timeout=60s \
interval=0s --group masterg-firstcluster
- Thiết lập failover postgres resource nếu số lượng lỗi (không thể kết nối) là một lần.
# pcs resource meta pgsql-firstcluster migration-threshold=1
- Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
* Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
* Masters: [ node1 ]
* Slaves: [ node2 ]
* Resource Group: masterg-firstcluster:
* pgFS-firstcluster (ocf::heartbeat:Filesystem): Started node1
* pgsql-firstcluster (ocf::heartbeat:pgsql): Started node1
...snip...
# ps -ef | grep postgres: | grep -v grep
postgres 11226 11217 0 03:47 ? 00:00:00 postgres: checkpointer
postgres 11227 11217 0 03:47 ? 00:00:00 postgres: background writer
postgres 11228 11217 0 03:47 ? 00:00:00 postgres: walwriter
postgres 11229 11217 0 03:47 ? 00:00:00 postgres: autovacuum launcher
postgres 11230 11217 0 03:47 ? 00:00:00 postgres: stats collector
postgres 11231 11217 0 03:47 ? 00:00:00 postgres: logical replication launcher
#
Thực hiện trên: Node1
Tạo VIP cho cluster
# sudo pcs resource create vip-firstcluster ocf:heartbeat:IPaddr2 ip=172.17.28.111 \
nic=ens33 cidr_netmask=28 op start timeout=60s interval=0s on-fail=restart \
op monitor timeout=120s interval=20s on-fail=restart op stop timeout=60s \
interval=0s on-fail=block --group masterg-firstcluster
- Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
* Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
* Masters: [ node1 ]
* Slaves: [ node2 ]
* Resource Group: masterg-firstcluster:
* pgFS-firstcluster (ocf::heartbeat:Filesystem): Started node1
* pgsql-firstcluster (ocf::heartbeat:pgsql): Started node1
* vip-firstcluster (ocf::heartbeat:IPaddr2): Started node1
...snip...
# ip a | grep -w inet
inet 127.0.0.1/8 scope host lo
inet 172.17.28.69/28 brd 172.17.28.79 scope global noprefixroute ens33
inet 172.17.28.111/28 scope global ens33
inet 192.168.91.131/24 brd 192.168.91.255 scope global dynamic noprefixroute ens37
#
Thực hiện trên: Node1
Tạo constraint cho cluster- Khởi động group master với DRBD trên cùng một Node
# sudo pcs constraint colocation add started masterg-firstcluster with Master \
drbd-fisrtcluster-clone INFINITY
- Khởi động theo thứ tự DRBD xong rồi master group
# sudo pcs constraint order promote drbd-fisrtcluster-clone then start \
masterg-firstcluster symmetrical=false score=INFINITY
Thực hiện trên: Node1
Test failover cluster- Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
* Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
* Masters: [ node1 ]
* Slaves: [ node2 ]
* Resource Group: masterg-firstcluster:
* pgFS-firstcluster (ocf::heartbeat:Filesystem): Started node1
* pgsql-firstcluster (ocf::heartbeat:pgsql): Started node1
* vip-firstcluster (ocf::heartbeat:IPaddr2): Started node1
...snip...
- Failover master resource sang node2
# pcs resource move masterg-firstcluster
Warning: Creating location constraint 'cli-ban-masterg-firstcluster-on-node1' with a score of -INFINITY for resource masterg-firstcluster on node1.
This will prevent masterg-firstcluster from running on node1 until the constraint is removed
This will be the case even if node1 is the last node in the cluster
- Kiểm tra trạng thái cluster
# crm_mon -Arf1
...snip...
Full List of Resources:
* Clone Set: drbd-fisrtcluster-clone [drbd-fisrtcluster] (promotable):
* Masters: [ node2 ]
* Slaves: [ node1 ]
* Resource Group: masterg-firstcluster:
* pgFS-firstcluster (ocf::heartbeat:Filesystem): Started node2
* pgsql-firstcluster (ocf::heartbeat:pgsql): Started node2
* vip-firstcluster (ocf::heartbeat:IPaddr2): Started node2
...snip...
- Xóa constraint tạo ra bởi lệnh move resource
# pcs resource clear masterg-firstcluster
Removing constraint: cli-ban-masterg-firstcluster-on-node1
Đến đây bạn đã có một PostgreSQL cluster tự động failover giữa các nodes nếu gặp lỗi.
Lời kết
Bao gồm pacemaker có rất nhiều cấu trúc cluster có thể áp dụng cho hệ thống của bạn. Bạn nên tham khảo vào mục đích sử dụng, yêu cầu từ hệ thống và business để lựa chọn cấu hình phù hợp với hệ thống của mình.
=============================
* KHOÁ HỌC ORACLE DATABASE A-Z ENTERPRISE trực tiếp từ tôi giúp bạn bước đầu trở thành những chuyên gia DBA, đủ kinh nghiệm đi thi chứng chỉ OA/OCP, đặc biệt là rất nhiều kinh nghiệm, bí kíp thực chiến trên các hệ thống Core tại VN chỉ sau 1 khoá học.
* CÁCH ĐĂNG KÝ: Gõ (.) hoặc để lại số điện thoại hoặc inbox
https://m.me/tranvanbinh.vn hoặc Hotline/Zalo 090.29.12.888
* Chi tiết tham khảo:
https://bit.ly/oaz_w
=============================
KẾT NỐI VỚI CHUYÊN GIA TRẦN VĂN BÌNH:
📧 Mail: binhoracle@gmail.com
☎️ Mobile/Zalo: 0902912888
👨 Facebook:
https://www.facebook.com/BinhOracleMaster
👨 Inbox Messenger:
https://m.me/101036604657441 (profile)
👨 Fanpage:
https://www.facebook.com/tranvanbinh.vn
👨 Inbox Fanpage:
https://m.me/tranvanbinh.vn
👨👩 Group FB:
https://www.facebook.com/groups/DBAVietNam
👨 Website:
https://www.tranvanbinh.vn
👨 Blogger:
https://tranvanbinhmaster.blogspot.com
🎬 Youtube:
https://www.youtube.com/@binhguru
👨 Tiktok:
https://www.tiktok.com/@binhguru
👨 Linkin:
https://www.linkedin.com/in/binhoracle
👨 Twitter:
https://twitter.com/binhguru
👨 Podcast:
https://www.podbean.com/pu/pbblog-eskre-5f82d6
👨 Địa chỉ: Tòa nhà Sun Square - 21 Lê Đức Thọ - Phường Mỹ Đình 1 - Quận Nam Từ Liêm - TP.Hà Nội
=============================
Cấu hình PostgreSQL cluster với pacemaker và DRBD, oracle tutorial, học oracle database, Tự học Oracle, Tài liệu Oracle 12c tiếng Việt, Hướng dẫn sử dụng Oracle Database, Oracle SQL cơ bản, Oracle SQL là gì, Khóa học Oracle Hà Nội, Học chứng chỉ Oracle ở đầu, Khóa học Oracle online,sql tutorial, khóa học pl/sql tutorial, học dba, học dba ở việt nam, khóa học dba, khóa học dba sql, tài liệu học dba oracle, Khóa học Oracle online, học oracle sql, học oracle ở đâu tphcm, học oracle bắt đầu từ đâu, học oracle ở hà nội, oracle database tutorial, oracle database 12c, oracle database là gì, oracle database 11g, oracle download, oracle database 19c, oracle dba tutorial, oracle tunning, sql tunning , oracle 12c, oracle multitenant, Container Databases (CDB), Pluggable Databases (PDB), oracle cloud, oracle security, oracle fga, audit_trail,oracle RAC, ASM, oracle dataguard, oracle goldengate, mview, oracle exadata, oracle oca, oracle ocp, oracle ocm , oracle weblogic, postgresql tutorial, mysql tutorial, mariadb tutorial, ms sql server tutorial, nosql, mongodb tutorial, oci, cloud, middleware tutorial, hoc solaris tutorial, hoc linux tutorial, hoc aix tutorial, unix tutorial, securecrt, xshell, mobaxterm, putty