Báo cáo thực hành cơ sở dữ liệu phân tán
Trang 1Hệ cơ sở dữ liệu phân tán
NHÓM 3
Báo cáo thực hành Cơ sở dữ liệu phân tán
Giảng viên hướng dẫn:
Nguyễn Tiến Long
Trang 2A PHÂN TÍCH VẤN ĐỀ
B Vấn đề
Ở hệ thống ngân hàng có 3 chi nhánh A, B và C được tọa lạc ở 3 nơi khác nhau Máy chủ ở mỗi chi nhánh của ngân hàng lưu thông tin của khách hàng và các giao dịch của khách hàng ở chi nhánh đó Ngoài ra, ở mỗi chi nhánh lưu thông tin về các chi nhánh của hệ thống ngân hàng
Ta cần phép phân mảnh ngang và xây dựng các procedure xử lý trên hệ quản trị
dữ liệu Oracle, để thực hiện các giao dịch: gửi tiền vào tài khoản, rút tiền từ tài khoản và chuyển tiền vào tài khoản trong hệ thống ngân hàng
Ta thực hiện thông qua các câu truy vấn phân tán, đồng thời tối ưu hóa truy vấn
để các giao dịch xảy ra an toàn và kết quả truy xuất nhanh hơn
C Bố trí dữ liệu
B TỔ CHỨC DỮ LIỆU
1 Qui định dữ liệu ở các chi nhánh
Tại chi nhánh A: Mã khách hàng bắt đầu bằng A, ví dụ: A001
Tại chi nhánh B: Mã khách hàng bắt đầu bằng B, ví dụ: B001
Chi nhánh C Chi nhánh B
Chi nhánh A
Trang 3Tại chi nhánh C: Mã khách hàng bắt đầu bằng C, ví dụ: C001
2 Xử lý giao dịch
Giao dịch gửi tiền: Phía khách hàng thực hiện gửi tiền từ bất kỳ một chi nhánh nào của hệ thống ngân hàng
Giao dịch rút tiên: Phía khách hàng thực hiện rút tiền từ bất kỳ một chi nhánh nào của hệ thống ngân hàng
Giao dịch chuyển tiền: Phía khách hàng thực hiện chuyển tiền từ bất kỳ một chi nhánh nào của hệ thống ngân hàng
3 Tổ chức dữ liệu ở các chi nhánh
3.1 Tổ chức dữ liệu trên máy chủ Chi Nhánh A
Tạo user và gán quyền cơ bản và quyền cho phép tạo database link cho user
Create user chinhanh_A identified by chinhanh_A;
create user chinhanh_A identified by chinhanh_A;
grant connect, resource to chinhanh_A;
grant create database link to chinhanh_A;
connect chinhanh_A / chinhanh_A;
Tạo các bảng
create table KHACHHANG(
MAKH varchar2(10) primary key,
TENKH varchar2(50),
TONGTIEN number
);
create table CHINHANH(
MACN varchar2(5) primary key,
TENCN varchar2(50)
);
create table GIAODICH(
MACN varchar2(5),
MAKH varchar2(10),
SOTIENGD number,
LOAIGD char(1)
);
Tạo Constraint
ALTER TABLE GIAODICH ADD CONSTRAINT FK_GD_KH FOREIGN KEY (MAKH)REFERENCES KHACHHANG(MAKH);
Trang 4ALTER TABLE GIAODICH ADD CONSTRAINT FK_GD_CN FOREIGN KEY (MACN) REFERENCES CHINHANH(MACN);
Insert dữ liệu
insert into KHACHHANG values('CN01001','Nguyen Van A',10000000);
insert into KHACHHANG values('CN01002','Nguyen Van B',15000000);
insert into CHINHANH values('CN01','Vietcombank');
insert into CHINHANH values('CN02','VBQ1');
insert into CHINHANH values('CN03','VBQ3');
Tạo Trigger để cập nhật lại số tiền khi khách hàng thực hiện một giao dịch
CREATE OR REPLACE TRIGGER capnhatgd
AFTER INSERT ON GIAODICH FOR EACH ROW
BEGIN
IF :NEW.LOAIGD = 'G' THEN UPDATE KHACHHANG
SET KHACHHANG.TONGTIEN=KHACHHANG.TONGTIEN + :NEW.SOTIENGD
WHERE KHACHHANG.MAKH=:NEW.MAKH;
ELSE
UPDATE KHACHHANG SET KHACHHANG.TONGTIEN=KHACHHANG.TONGTIEN
- :NEW.SOTIENGD WHERE KHACHHANG.MAKH=:NEW.MAKH;
END IF;
END;
3.2 Tổ chức dữ liệu trên máy chủ Chi Nhánh B
Tạo user và gán quyền cơ bản và quyền cho phép tạo database link cho user
Create user chinhanh_B identified by chinhanh_B;
create user chinhanh_B identified by chinhanh_B;
grant connect, resource to chinhanh_B;
grant create database link to chinhanh_B;
connect chinhanh_B/ chinhanh_B;
Tạo các bảng
create table KHACHHANG(
MAKH varchar2(10) primary key,
Trang 5TENKH varchar2(50),
TONGTIEN number
);
create table CHINHANH(
MACN varchar2(5) primary key,
TENCN varchar2(50)
);
create table GIAODICH(
MACN varchar2(5),
MAKH varchar2(10),
SOTIENGD number,
LOAIGD char(1)
);
Tạo Constraint
ALTER TABLE GIAODICH ADD CONSTRAINT FK_GD_KH FOREIGN KEY (MAKH) REFERENCES KHACHHANG(MAKH);
ALTER TABLE GIAODICH ADD CONSTRAINT FK_GD_CN FOREIGN KEY (MACN) REFERENCES CHINHANH(MACN);
Insert dữ liệu
insert into KHACHHANG values(‘CN02001’,'Nguyen Thi C',10000000);
insert into KHACHHANG values(‘CN02001’,'Tran Thi D',15000000);
insert into CHINHANH values('CN01','Vietcombank');
insert into CHINHANH values('CN02','VBQ1');
insert into CHINHANH values('CN03','VBQ3');
Tạo Trigger để cập nhật lại số tiền khi khách hàng thực hiện một giao dịch
CREATE OR REPLACE TRIGGER capnhatgd
AFTER INSERT ON GIAODICH
FOR EACH ROW
BEGIN
IF :NEW.LOAIGD = 'G' THEN
UPDATE KHACHHANG SET KHACHHANG.TONGTIEN=KHACHHANG.TONGTIEN + :NEW.SOTIENGD
WHERE KHACHHANG.MAKH=:NEW.MAKH;
ELSE
UPDATE KHACHHANG
Trang 6SET KHACHHANG.TONGTIEN=KHACHHANG.TONGTIEN
- :NEW.SOTIENGD WHERE KHACHHANG.MAKH=:NEW.MAKH;
END IF;
END;
3.3 Tổ chức dữ liệu trên máy chủ Chi Nhánh C
Tạo user và gán quyền cơ bản và quyền cho phép tạo database link cho user
Create user chinhanh_C identified by chinhanh_C;
create user chinhanh_C identified by chinhanh_C;
grant connect, resource to chinhanh_C;
grant create database link to chinhanh_C;
connect chinhanh_C/ chinhanh_C;
Tạo các bảng
create table KHACHHANG(
MAKH varchar2(10) primary key,
TENKH varchar2(50),
TONGTIEN number
);
create table CHINHANH(
MACN varchar2(5) primary key,
TENCN varchar2(50)
);
create table GIAODICH(
MACN varchar2(5),
MAKH varchar2(10),
SOTIENGD number,
LOAIGD char(1)
);
Tạo Constraint
ALTER TABLE GIAODICH ADD CONSTRAINT FK_GD_KH FOREIGN KEY (MAKH) REFERENCES KHACHHANG(MAKH);
ALTER TABLE GIAODICH ADD CONSTRAINT FK_GD_CN FOREIGN KEY (MACN) REFERENCES CHINHANH(MACN);
Insert dữ liệu
Trang 7insert into KHACHHANG values(‘CN03001’,'Le Thi E',10000000);
insert into KHACHHANG values(‘CN03001’,Phan Van G',15000000);
insert into CHINHANH values('CN01','Vietcombank');
insert into CHINHANH values('CN02','VBQ1');
insert into CHINHANH values('CN03','VBQ3');
Tạo Trigger để cập nhật lại số tiền khi khách hàng thực hiện một giao dịch
CREATE OR REPLACE TRIGGER capnhatgd
AFTER INSERT ON GIAODICH
FOR EACH ROW
BEGIN
IF :NEW.LOAIGD = 'G' THEN
UPDATE KHACHHANG SET KHACHHANG.TONGTIEN=KHACHHANG.TONGTIEN + :NEW.SOTIENGD
WHERE KHACHHANG.MAKH=:NEW.MAKH;
ELSE
UPDATE KHACHHANG SET KHACHHANG.TONGTIEN=KHACHHANG.TONGTIEN
- :NEW.SOTIENGD WHERE KHACHHANG.MAKH=:NEW.MAKH;
END IF;
END;
C TẠO DATABASE LINK
Ta cần tạo database link từ A đến B đến C Và để tạo một link từ máy B đến máy C, ta phải thực hiện cấu hình trên cả 2 máy để chúng nhận ra nhau
1 Trên máy chủ B (máy chủ C tương tự)
Tạo các role và gán quyền:
Thực hiện trên user sys hoặc system:
CREATE ROLE ROLE_GD NOT IDENTIFIED;
GRANT insert,select ON chinhanh_B.giaodich TO ROLE_GD;
GRANT select on chinhanh_B.khachhang to ROLE_GD;
Tạo một user để chia quyền truy cập giới hạn các bảng và cấp cho máy cần tạo link đến
CREATE USER guest IDENTIFIED BY guest;
GRANT CONNECT TO guest;
Gán ROLE_GD cho guest:
GRANT ROLE_GD to guest;
Kiểm tra xem Role đã được tạo hợp lệ:
Trang 8Connect guest / guest:
select * from chinhanh_B.khachhang
Vào Net Manager->mở Local
Mở Listener
Trong ô host: ip máy chủ Chi Nhánh B
2 Trên máy chủ A
Connect chinhanh_A/ chinhanh_A;
Với mỗi chi nhánh, ta tạo một database link để thực hiện truy vấn phân tán
Vào Net Manager->mở Local
Cấu hình để tạo liên kết đến Chi Nhánh B:
Click dấu + để thêm một instance cho phép tạo link đến máy chủ CN02
Net Service Name: chinhanh_A (tự đặt) ->Next
Chọn TCP/IP (Internet Protocol)->Next
Host Name: ip của máy chủ Chi Nhánh B
Service Name: orcl(tên service name của máy chủ Chi Nhánh B)
Nhấn finish để kết thúc
Cấu hình để tạo liên kết đến Chi Nhánh C:
Click dấu + để thêm một instance cho phép tạo link đến máy chủ Chi Nhánh C
Net Service Name: loc(tự đặt) ->Next
Chọn TCP/IP (Internet Protocol)->Next
Host Name: ip của máy chủ Chi Nhánh C
Service Name: orcl(tên service name của máy chủ Chi Nhánh C)
Nhấn finish để kết thúc
Lưu ý: start lại các services để ghi nhận sự thay đổi cấu hình
3 Tạo database link đến từ chi nhánh Chi Nhánh A đến Chi Nhánh B và Chi Nhánh C:
CREATE DATABASE LINK DBL_VINH CONNECT TO GUEST IDENTIFIED BY GUEST USING 'vinh' CREATE DATABASE LINK DBL_LOC CONNECT TO GUEST IDENTIFIED BY GUEST USING 'loc'
Thực hiện truy vấn kết quả để test link vừa tạo:
Select * from khachhang UNION
Select * from chinhanh_B.khachhang@DBL_CHINHANHB UNION
Select * from chinhanh_C.khachhang@DBL_CHINHANHC
Kết quả truy vấn:
HÌNH 1
D XỬ LÝ GIAO DỊCH GIỮA CÁC CHI NHÁNH
Những điều cần chú ý:
Trang 9Set thời gian wait time ví dụ 5 giây: dbms_lock.sleep(5);
Để thực hiện được lệnh dbms_lock.sleep(5), ta phải gán quyền cho nó(dùng user sys): GRANT EXECUTE ON KHACHHANG TO PUBLIC;
Set mức cô lập SERIALIZABLE để tránh các hiện tượng như Dirty Read,
Non-Repeatable Read và Phantom:SET TRANSACTION ISOLATION LEVEL
SERIALIZABLE;
Để gọi được các proc, ta phải sử dụng câu lệnh: Set serveroutput on;
1 Gửi tiền tại chi nhánh A:
a Ý tưởng:
Đầu vào sẽ là mã khách hàng và số tiền gửi Máy chủ ở chi nhánh A thực hiện phân tích chuỗi MAKH và lấy ra 4 ký tự đầu tiên của chuỗi:
Nếu MAKH được bắt đầu bằng chuỗi “chi nhánh A”, điều này chứng tỏ thông tin khách hàng được lưu trên chính máy chủ chi nhánh A Hệ thống thực hiện kiểm tra khách hàng trên máy chủ chi nhánh A và cộng tiền khách hàng trong bảng
KHACHHANG nếu tồn tại khách hàng đó, đồng thời chèn một dòng dữ liệu vào bảng GIAODICH với LOAIGD là “G”
Nếu MAKH được bắt đầu bằng chuỗi “chi nhánh B”, điều này chứng tỏ thông tin khách hàng được lưu trên máy chủ chi nhánh B Hệ thống thực hiện kiểm tra khách hàng trên máy chủ chi nhánh B và cộng tiền khách hàng trong bảng
chinhanh_B.KHACHHANG nếu tồn tại khách hàng đó, đồng thời chèn một dòng
dữ liệu vào bảng chinhanh_B.GIAODICH với LOAIGD là “G” thông qua
DBL_CHINHANHB
Nếu MAKH được bắt đầu bằng chuỗi “chi nhánh c”, điều này chứng tỏ thông tin khách hàng được lưu trên máy chủ chi nhánh B Hệ thống thực hiện kiểm tra khách hàng trên máy chủ chi nhánh B và cộng tiền khách hàng trong bảng
chinhanh_C.KHACHHANG nếu tồn tại khách hàng đó, đồng thời chèn một dòng
dữ liệu vào bảng chinhanh_C.GIAODICH với LOAIGD là “G” thông qua
DBL_CHINHANHC
Nếu MAKH không thuộc vào ba trường hợp trên, thông báo cho người sử dụng rằng thông tin về mã khách hàng không chính xác
b Procedure gửi tiền tại chi nhánh CN01:
create or replace procedure guitien(v_MAKH in
varchar2,v_money in Number)
As
dem int;
Begin
Trang 10SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
if(substr(v_MAKH,0,4) = 'CNA') THEN
select count(MAKH) into dem from KHACHHANG where MAKH = v_MAKH;
if(dem>0) then
insert into GIAODICH values('CNA',v_MAKH,v_money,'G');
DBMS_OUTPUT.PUT_LINE('Gửi tiền thành công!');
else
DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
elsif(substr(v_MAKH,0,4) = 'CNB') THEN
select count(MAKH) into dem from
chinhanh_B.KHACHHANG@DBL_CHINHANHB where MAKH = v_MAKH; if(dem>0) then
insert into chinhanh_B.GIAODICH@DBL_CHINHANHB values('CN01',v_MAKH,v_money,'G');
DBMS_OUTPUT.PUT_LINE('Gửi tiền thành công!');
else
DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
elsif(substr(v_MAKH,0,4) = 'CNC') THEN
select count(MAKH) into dem from
chinhanh_C.KHACHHANG@DBL_CHINHANHC where MAKH = v_MAKH; if(dem>0) then
insert into chinhanh_C.GIAODICH@DBL_CHINHANHC values('CN01',v_MAKH,v_money,'G');
DBMS_OUTPUT.PUT_LINE('Gửi tiền thành công!');
else
DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
else
DBMS_OUTPUT.PUT_LINE('Mã khách hàng không đúng');
end if;
COMMIT;
End;
c Kết quả chạy thử:
Gửi tiền vào khách hàng Chi Nhánh A:
HÌNH 2
HÌNH 3
Trang 11Gửi tiền vào khách hàng Chi Nhánh B:
HÌNH 4
HÌNH 5
Gửi tiền với mã khách hàng không đúng:
HÌNH 6
Gửi tiền với mã khách hàng không tồn tại:
HÌNH 7
2 Rút tiền tại chi nhánh A:
a Ý tưởng:
Đầu vào sẽ là mã khách hàng và số tiền rút Máy chủ ở Chi Nhánh A thực hiện phân tích chuỗi MAKH và lấy ra 4 ký tự đầu tiên của chuỗi:
Nếu MAKH được bắt đầu bằng chuỗi “CNA”, điều này chứng tỏ thông tin khách hàng được lưu trên chính máy chủ Chi Nhánh A Hệ thống thực hiện kiểm tra khách hàng trên máy chủ Chi Nhánh A và kiểm tra số tiền có trong tài khoản của khách hàng Hệ thống thực hiện trừ tiền khách hàng trong bảng KHACHHANG nếu tồn tại khách hàng và số tiền còn lại lớn hơn số tiền rút ít nhất là 50000, đồng thời chèn một dòng dữ liệu vào bảng GIAODICH với LOAIGD là “R”
Nếu MAKH được bắt đầu bằng chuỗi “CNB”, điều này chứng tỏ thông tin khách hàng được lưu trên máy chủ Chi Nhánh B Hệ thống thực hiện kiểm tra khách hàng trên máy chủ Chi Nhánh B kiểm tra số tiền có trong tài khoản của khách hàng Hệ thống thực hiệntrừ tiền khách hàng trong bảng vinh_ddbms.KHACHHANG nếu tồn tại khách hàng và số tiền còn lại lớn hơn số tiền rút ít nhất là 50000, đồng thời chèn một dòng dữ liệu vào bảng vinh_ddbms.GIAODICH với LOAIGD là “R” thông qua DBL_CHINHANHB
Nếu MAKH được bắt đầu bằng chuỗi “CNC”, điều này chứng tỏ thông tin khách hàng được lưu trên máy chủ Chi Nhánh C Hệ thống thực hiện kiểm tra khách hàng trên máy chủ Chi Nhánh C và kiểm tra số tiền có trong tài khoản của khách hàng
Hệ thống thực hiệntrừ tiền khách hàng trong bảng chinhanh_C.KHACHHANG nếu tồn tại khách hàng và số tiền còn lại lớn hơn số tiền rút ít nhất là 50000, đồng thời chèn một dòng dữ liệu vào bảng loc_ddbms.GIAODICH với LOAIGD là “R” thông qua DBL_CHINHANHC
Trang 12Nếu MAKH không thuộc vào ba trường hợp trên, thông báo cho người sử dụng rằng thông tin về mã khách hàng không chính xác
b Procedure rút tiền tại chi nhánh CNA:
create or replace procedure ruttien(v_MAKH in varchar2,v_money in Number)
As
dem int;
tongtien int;
Begin
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
if(substr(v_MAKH,0,4) = 'CNA') THEN
select count(MAKH) into dem from KHACHHANG where MAKH
= v_MAKH;
if(dem>0) then select tongtien into tongtien from KHACHHANG where MAKH = v_MAKH;
if(tongtien-v_money>= 50000) then insert into GIAODICH
values('CNA',v_MAKH,v_money,'R');
DBMS_OUTPUT.PUT_LINE('Rút tiền thành công!'); else
DBMS_OUTPUT.PUT_LINE('Bạn không đủ tiền rút!'); end if;
else DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
elsif(substr(v_MAKH,0,4) = 'CNB') THEN
select count(MAKH) into dem from chinhanh_B.KHACHHANG@DBL_CHINHANHB where MAKH = v_MAKH;
if(dem>0) then select tongtien into tongtien from KHACHHANG where MAKH = v_MAKH;
if(tongtien-v_money>= 50000) then insert into GIAODICH
values('CNA',v_MAKH,v_money,'R');
DBMS_OUTPUT.PUT_LINE('Rút tiền thành công!'); else
DBMS_OUTPUT.PUT_LINE('Bạn không đủ tiền rút!'); end if;
else
Trang 13DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
elsif(substr(v_MAKH,0,4) = 'CN02') THEN
select count(MAKH) into dem from chinhanh_B.KHACHHANG@DBL_CHINHANHB where MAKH = v_MAKH;
if(dem>0) then select tongtien into tongtien from chinhanh_B.KHACHHANG@DBL_CHINHANHB where MAKH = v_MAKH;
if(tongtien-v_money >= 50000) then insert into chinhanh_B.GIAODICH@DBL_CHINHANHB values('CNA',v_MAKH,v_money,'R');
DBMS_OUTPUT.PUT_LINE('Rút tiền thành công!'); else
DBMS_OUTPUT.PUT_LINE('Bạn không đủ tiền rút!'); end if;
else
DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
elsif(substr(v_MAKH,0,4) = 'CN03') THEN select count(MAKH) into dem from loc_ddbms.KHACHHANG@DBL_LOC where MAKH = v_MAKH; if(dem>0) then
select tongtien into tongtien from chinhanh_C.KHACHHANG@DBL_CHINHANHC where MAKH = v_MAKH;
if(tongtien-v_money >= 50000) then insert into chinhanh_C.GIAODICH@DBL_CHINHANHC values('CNA',v_MAKH,v_money,'G');
DBMS_OUTPUT.PUT_LINE('Rút tiền thành công!'); else
DBMS_OUTPUT.PUT_LINE('Bạn không đủ tiền rút!'); end if;
else
DBMS_OUTPUT.PUT_LINE('Không tồn tại khách hàng này');
end if;
else
DBMS_OUTPUT.PUT_LINE('Mã khách hàng không đúng');
end if;