1. Trang chủ
  2. » Luận Văn - Báo Cáo

Xây dựng mô-đun sinh tự động mã nguồn trigger trên ngôn ngữ C phục vụ cập nhật gia tăng đồng bộ các khung nhìn thực với truy vấn lồng cho PostgreSQL

26 3 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 26
Dung lượng 697,37 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Cập nhật gia tăng CNGT là kỹ thuật cập nhật dữ liệu trên KNT một cách đồng bộ, được thực hiện mỗi khi dữ liệu tại các bảng gốc BG tham gia vào KNT có sự thay đổi, nhờ đó giúp cho KNT luô

Trang 1

ĐẠI HỌC ĐÀ NẴNG

TRƯỜNG ĐẠI HỌC SƯ PHẠM



LÊ THỊ THẢO NGUYÊN

XÂY DỰNG MÔ-ĐUN SINH TỰ ĐỘNG MÃ NGUỒN TRIGGER TRÊN NGÔN NGỮ C PHỤC VỤ CẬP NHẬT GIA TĂNG, ĐỒNG BỘ CÁC KHUNG NHÌN THỰC VỚI

TRUY VẤN LỒNG CHO POSTGRESQL

Chuyên ngành: Hệ thống thông tin

Mã số: 8480104

TÓM TẮT LUẬN VĂN THẠC SĨ

HỆ THỐNG THÔNG TIN

Đà Nẵng – Năm 2018

Trang 2

Công trình được hoàn thành tại

TRƯỜNG ĐẠI HỌC SƯ PHẠM

Người hướng dẫn khoa học:

TS Nguyễn Trần Quốc Vinh

Phản biện 1: PGS TS Nguyễn Thanh Bình

Phản biện 2: GS TS Nguyễn Thanh Thủy

Luận văn sẽ được bảo vệ trước Hội đồng chấm Luận văn tốt nghiệp thạc sĩ Hệ thống thông tin họp tại

Trường Đại học Sư phạm vào ngày 18 tháng 11 năm

2018

Có thể tìm hiểu luận văn tại:

Thư viện Trường Đại học Sư phạm – ĐHĐN

Khoa Tin Học, Trường Đại học Sư phạm – ĐHĐN

Trang 3

LỜI MỞ ĐẦU

1 Lý do chọn đề tài

Khung nhìn thực (KNT) là một kỹ thuật giúp cải thiện và nâng cao tốc độ thực thi đối với các truy vấn phức tạp, có tần suất sử dụng cao trên một lượng dữ liệu lớn Đối với những truy vấn phức tạp bao gồm nhiều phép nối và các hàm thống kê, hiệu quả sử dụng KNT càng rõ rệt, đặc biệt khi áp dụng trên một lượng dữ liệu đủ lớn Đến nay, kỹ thuật KNT đã được triển khai trên các hệ quản trị cơ sở dữ liệu (HTQCSDL) thương mại lớn như Oracle, Microsoft SQL Server, IBM DB2,… và ngày càng được ứng dụng rộng rãi

PostgreSQL là một HQTCSDL mã nguồn mở hàng đầu trên thế giới, tuy nhiên KNT mới được triển khai trên PostgreSQL ở phiên bản 9.3.4 và chưa hỗ trợ vấn đề cập nhật đồng bộ gia tăng Thay vào

đó, PostgreSQL cập nhật KNT theo cơ chế toàn phần bất đồng bộ, tức là thực thi lại toàn bộ truy vấn dùng để tạo KNT mỗi khi cần cập nhật Điều này tốn chi phí xấp xỉ chi phí thực hiện truy vấn, và không đảm bảo được dữ liệu trên KNT luôn luôn là mới nhất Đến phiên bản 10 có bổ sung tính năng cập nhật đồng thời, tuy nhiên tính năng này chỉ hỗ trợ việc truy cập đồng thời đến KNT, nghĩa là cung cấp khả năng truy cập bảng KNT để trả lời truy vấn ngay cả khi nó đang

được cập nhật bằng lệnh refresh materialized view, chứ chưa đề cập

đến vấn đề CNGT

Cập nhật gia tăng (CNGT) là kỹ thuật cập nhật dữ liệu trên KNT một cách đồng bộ, được thực hiện mỗi khi dữ liệu tại các bảng gốc (BG) tham gia vào KNT có sự thay đổi, nhờ đó giúp cho KNT luôn trong trạng thái được cập nhật Do vậy, việc nghiên cứu các kỹ thuật CNGT cho KNT trên PostgesSQL đang rất được quan tâm Việc CNGT KNT có thể được thực hiện thông qua việc xây dựng các trigger bắt các sự kiện làm thay đổi dữ liệu trên các bảng gốc, từ đó tiến hành xác định các thay đổi có thể làm ảnh hưởng đến tính đúng đắn của kết quả được lưu trong KNT, sau đó tiến hành việc cập nhật dữ liệu trong KNT PostgreSQL hỗ trợ 2 loại trigger là trigger viết bằng ngôn ngữ PL/pgSQL và trigger viết bằng ngôn ngữ

C Đã có nghiên cứu về việc sử dụng trigger mã nguồn PL/pgSQL để CNGT đồng bộ cho KNT trong PostgreSQL [2, 3, 5], nhưng trigger

mã nguồn PL/pgSQL được đánh giá là có hiệu năng chưa cao ở hầu hết các xử lý so với trigger trong ngôn ngữ C, trigger trên ngôn ngữ

Trang 4

C thực thi nhanh hơn so với trigger trên ngôn ngữ PL/pgSQL (khoảng 13%) Vì vậy, nghiên cứu này đề xuất sử dụng ngôn ngữ C làm mã nguồn cho trigger và xây dựng mô-đun để sinh tự động các trigger cho tất cả các BG tham gia vào truy vấn, phục vụ thực hiện CNGT KNT trong cơ chế đồng bộ, như một phần của giao tác thực hiện thao tác dữ liệu trong các BG

Đã có các nghiên cứu [1, 2, 3] xây dựng được chương trình sinh

mã nguồn trigger tự động bằng ngôn ngữ C, triển khai các thuật toán CNGT KNT trên HQTCSDL PostgreSQL Tuy nhiên nghiên cứu này vẫn chưa quan tâm đến các KNT được tạo bởi truy vấn lồng, truy vấn

đệ quy, truy vấn bao gồm phép nối ngoài Có thể thấy truy vấn lồng (SubQuery) là một dạng truy vấn phổ biến, tần suất xuất hiện cao, tuy nhiên các nghiên cứu về CNGT KNT cho PostgreSQL đến nay vẫn chưa hỗ trợ dạng truy vấn này

Vì vậy, tôi chọn đề tài “Xây dựng mô-đun sinh tự động mã nguồn trigger trên ngôn ngữ C phục vụ cập nhật gia tăng, đồng bộ các khung nhìn thực với truy vấn lồng cho PostgreSQL” làm khóa

luận tốt nghiệp cao học

2 Mục tiêu và nhiệm vụ đề tài

2.1 Mục tiêu

- Xây dựng chương trình sinh tự động mã nguồn trigger trên ngôn ngữ C phục vụ cập nhật gia tăng, đồng bộ các khung nhìn thực với truy vấn lồng trong PostgreSQL

- Chương trình có khả năng sinh mã SQL cài đặt khung nhìn thực, trigger trên các bảng gốc để cập nhật gia tăng, đồng bộ các khung nhìn thực

- Khai thác các thuật toán CNGT KNT đã có để ứng dụng vào

đề tài, đặc biệt là thuật toán CNGT KNT với truy vấn lồng

3 Đối tƣợng và phạm vi nghiên cứu

3.1 Đối tƣợng nghiên cứu

- CSDL quan hệ, HQT CSDL quan hệ, ngôn ngữ lập trình C

- Trigger trên các HQT CSDL quan hệ

Trang 5

- Truy vấn lồng, khung nhìn thực

- Thuật toán CNGT KNT với truy vấn lồng

3.2 Phạm vi nghiên cứu

- HQT CSDL PostgreSQL

- Kỹ thuật viết trigger cho PostgreSQL bằng ngôn ngữ C

- Cách sử dụng trigger được viết bằng ngôn ngữ C trên PostgreSQL

- Các thuật toán CNGT cho KNT trên PostgreSQL

- Thuật toán CNGT KNT hỗ trợ truy vấn lồng

4 Phương pháp nghiên cứu

Về phương pháp nghiên cứu, tôi sử dụng hai phương pháp chính là nghiên cứu lý thuyết và nghiên cứu thực nghiệm

4.1 Phương pháp lý thuyết

Thu thập, chọn lọc, phân loại, ghi chú và nghiên cứu các tài liệu (sách, bài báo, luận văn, trang web) có liên quan đến khung nhìn thực, HQTCSDL PostgreSQL, cập nhật gia tăng KNT, đồng

bộ KNT, sinh mã trigger trong ngôn ngữ C

4.2 Phương pháp thực nghiệm

Dựa trên lý thuyết đã nghiên cứu, tiến hành xây dựng chương trình sinh tự động mã các trigger thực hiện cập nhật gia tăng khung nhìn thực với truy vấn lồng trong hệ cơ sở dữ liệu PostgreSQL; thử nghiệm trên máy đơn và đánh giá tốc độ cập nhật dữ liệu trên các bảng gốc (BG) có trigger cập nhật KNT

5 Ý nghĩa khoa học và thực tiễn của đề tài

5.1 Ý nghĩa khoa học

- Đề xuất thuật toán cập nhật gia tăng KNT truy vấn lồng

- Đề xuất thuật toán sinh tự động mã nguồn các trigger trong ngôn ngữ C phục vụ cập nhật gia tăng các bảng khung nhìn thực truy vấn lồng trong hệ quản trị cơ sở dữ liệu PostgreSQL

5.2 Ý nghĩa thực tiễn

Áp dụng chương trình vào cơ sở dữ liệu PostgreSQL nhằm làm tăng tốc độ thực thi các truy vấn dữ liệu mà vẫn đảm bào ràng buộc toàn vẹn dữ liệu Chương trình sinh tự động mã trigger C thực hiện CNGT KNT có tính ứng dụng cao, giúp tiết kiệm thời gian và công sức của người quản trị CSDL khi làm việc với HQTCSDL PostgreSQL cũng như các HQTCSDL mã nguồn mở

Trang 6

có hỗ trợ trigger trong ngôn ngữ C Chương trình sinh tự động mã nguồn các trigger có thể hỗ trợ các lập trình viên sinh mã trigger

6 Cấu trúc của luận văn

Chương 1: Nghiên cứu tổng quan, chương này giới thiệu

tổng quan về ngôn ngữ lập trình C, truy vấn lồng và KNT; cập nhật gia tăng, đồng bộ KNT Trình bày các vấn đề liên quan đến trigger trên C trong PostgreSQL

Chương 2: Khung nhìn thực trong PostgreSQL và thuật toán

cập nhật gia tăng khung nhìn thực với truy vấn lồng, chương này trình bày các phương pháp cập nhật KNT; phân tích thuật toán cập nhật gia tăng KNT với truy vấn lồng

Chương 3: Xây dựng chương trình sinh tự động mã nguồn

các trigger thực hiện cập nhật gia tăng khung nhìn thực với truy vấn lồng, chương này trình bày cách cài đặt môi trường CSDL và ngôn ngữ lập trình; xây dựng mô-đun sinh mã tự động trigger

Trang 7

CHƯƠNG 1 NGHIÊN CỨU TỔNG QUAN

1.1 Tổng quan về ngôn ngữ lập trình C

1.1.1 Ngôn ngữ lập trình C

C là ngôn ngữ rất có hiệu quả và được ưa chuộng để viết các phần mềm hệ thống, mặc dù nó cũng được dùng cho việc viết các ứng dụng C là ngôn ngữ lập trình tương đối nhỏ gọn vận hành gần với phần cứng, được tạo ra với một mục tiêu là làm cho nó thuận tiện để viết các chương trình lớn

1.1.2 Đặc điểm của ngôn ngữ C

Ngôn ngữ C có các đặc điểm sau:

C cũng được sử dụng để lập trình bậc thấp

C cung cấp nhiều hàm có sẵn giúp việc phát triển các ứng dụng trở nên nhanh chóng hơn

Ngôn ngữ C có khả năng mở rộng vì nó dễ dàng nhận một tính năng mới

1.2 Tổng quan về truy vấn lồng

1.2.1 Đặc điểm của truy vấn lồng

Là dạng truy vấn mà câu lệnh Select lồng trong câu lệnh select

Câu lệnh Select bên ngoài gọi là truy vấn ngoài

Câu lệnh Select bên trong gọi là truy vấn trong hay truy vấn con

Các câu lệnh Select có thể lồng nhau ở nhiều mức

Câu truy vấn con thường trả về một tập các giá trị

Trang 8

Mệnh đề Where của câu truy vấn ngoài

<biểu thức><so sánh tập hợp><truy vấn con>

- So sánh tập hợp thường đi cùng với một số toán tử IN, NOT IN, ALL, ANY, EXISTS…

WHERE … (SELECT B, C FROM Y) …

Ví dụ: Đưa ra mã, tên của những sinh viên thuộc lớp CNTT 1 SELECT ma_sv, ten_sv

- Truy vấn lồng tương quan: Khi nội dung của câu truy vấn con phụ thuộc vào câu truy vấn cha

Cú pháp:

SELECT A

FROM X

WHERE … (SELECT B, C FROM Y WHERE B = X.A) …

Ví dụ: Đưa ra mã, tên của những sinh viên thuộc lớp CNTT 1 SELECT ma_sv, ten_sv

Trang 9

Ở ví dụ này, câu truy vấn con SELECT* FROM Lop WHERE ma_lop = sinhvien.ma_lop and ten_lop = „CNTT – 1‟ WHERE ma_lop = sinhvien.ma_lop có sử dụng thành phần của câu truy vấn cha qua biểu thức so sánh ma_lop = sinhvien.ma_lop Do đó, đây là một câu truy vấn lồng tương quan

1.3 Tổng quan về khung nhìn thực

1.3.1 Giới thiệu chung

Khung nhìn thực (KNT - Materialized view) là một đối tượng trong cơ sở dữ liệu (CSDL) dùng để lưu trữ kết quả thực thi của một truy vấn, giúp cải thiện và nâng cao tốc độ thực thi đối với các truy vấn phức tạp, có tần suất sử dụng cao trên một lượng

dữ liệu lớn Ý tưởng của KNT là dựa trên các bảng kết quả sẵn có

để trả lời truy vấn một cách nhanh chóng mà không cần thực thi lại truy vấn Hiệu quả sử dụng KNT càng rõ rệt đặc biệt khi áp dụng trên một lượng dữ liệu đủ lớn, do đã bỏ qua các bước thực thi phép nối và các hàm thống kê vốn là những thành phần chiếm nhiều chi phí trong quá trình thực thi truy vấn

Tuy nhiên, việc sử dụng KNT cũng có những nhược điểm;

đó là: KNT làm tiêu tốn không gian lưu trữ và phải được cập nhật khi các bảng chi tiết cơ bản được sửa đổi

1.3.2 Phân loại khung nhìn thực

Phân loại khung nhìn thực theo một số loại [15] như sau:

1.3.2.1 KNT bản sao (snapshot materialized view) 1.3.2.2 KNT hăm hở (eager materialized view)

1.3.2.3 KNT rất lười (very lazy materialized view): 1.3.2.4 KNT lười (lazy materialized view):

1.4 Tổng quan về cập nhật gia tăng, đồng bộ khung nhìn thực

1.4.1 Tổng quan về cập nhật gia tăng

Cập nhật gia tăng chỉ sửa đổi nội dung KNT tương ứng với các thay đổi trong các bảng gốc Thông thường, cập nhật gia tăng đòi hỏi chi phí tài nguyên rất nhỏ so với cập nhật hoàn toàn

Để duy trì các bảng KNT trong trạng thái thực tiễn, cần phải cập nhật chúng mỗi khi có sự thay đổi dữ liệu trong các bảng gốc Trên thực tế, có các bài toán của hệ thống thông tin đòi hỏi phải tính đến một cách không chậm trễ chỉ một phần trong số các thay đổi dữ liệu trong các bảng gốc Từ đó xuất hiện khả năng trì hoãn

Trang 10

cập nhật KNT Khả năng đó cho phép giảm số lượng các cập nhật KNT, thông qua đó nâng cao đáng kể năng suất tổng thể của hệ thống

1.5 Cập nhật khung nhìn thực bằng trigger trên C trong PostgreSQL

1.5.1 Khái niệm về trigger

Trigger là một thủ tục đặc biệt mà việc thực thi của nó tự động khi có sự kiện xảy ra, các sự kiện gọi thủ tục đặc biệt này được định nghĩa trong câu lệnh, thông thường được thực hiện với các sự kiện liên quan đến Insert, Update, Delete dữ liệu Trigger được sử dụng trong việc bảo đảm toàn vẹn dữ liệu theo quy tắc xác định, được quản lý theo bảng dữ liệu hoặc khung nhìn

1.5.2 Trigger trên các HQT CSDL

Trigger có thể được thực thi trước hoặc sau khi sự kiện xảy

ra, bao gồm các mức:

Row Level Trigger

Column Level Trigger

For Each Row Type

For Each Statement Type

1.5.3 Trigger trong PostgreSQL

Trigger trên PostgreSQL có thể xử lý một tập các bản ghi, hoặc chỉ xử lý một bản ghi Chỉ trigger xử lý một bản ghi mới có thể nhìn thấy dữ liệu đang được thao tác Vì vậy đề tài thực hiện sinh mã nguồn trigger bắt sự kiện thay đổi dữ liệu trên các BG theo cơ chế xử lý từng bản ghi một trong tập các bản ghi được cập nhật

1.5.4 Hàm trong C

Hàm trong ngôn ngữ C có thể được biên dịch thành các thư viện chia sẻ với các phần mở rộng tương ứng là *.dll (trên hệ điều hành Windows)

Trang 11

1.5.5 Hàm trigger trong C

Khi một hàm được khai báo trả về kiểu trigger và được nạp vào server, có thể tạo hàm trigger bằng lệnh: CREATE TRIGGER

<tên trigger> {BEFORE|AFTER} {INSERT|DELETE|UPDATE}

ON <tên bảng> FOR EACH ROW EXECUTE PROCEDURE

<tên hàm C>

1.5.6 Ví dụ tạo trigger trên C trong PostgreSQL

Theo ví dụ tạo trigger trên C trong PostgreSQL (phụ lục 1)

thì hàm trigf báo cáo số lượng hàng trong bảng ttest và bỏ qua

phép toán thực tế nếu lệnh cố gắng chèn một giá trị rỗng vào cột

x (Vì trigger hoạt động như một ràng buộc không rỗng nhưng không hủy bỏ giao tác) [13]

1.6 Kết chương 1

Chương 1 đã giới thiệu các đối tượng mà đề tài đang làm việc trực tiếp là ngôn ngữ C, trigger cũng như những đặc điểm của trigger trong PostgreSQL và cách thức sử dụng các hàm C để xây dựng thành hàm trigger và cài đặt vào cơ sở dữ liệu Việc hiểu rõ những đặc thù về trigger trong PostgreSQL và khả năng của ngôn ngữ C trong việc triển khai các hàm trigger trong PostgreSQL đóng vai trò quan trọng trong việc triển khai thuật toán CNGT

Trang 12

CHƯƠNG 2 KHUNG NHÌN THỰC TRONG POSTGRESQL VÀ THUẬT TOÁN CẬP NHẬT GIA TĂNG KHUNG NHÌN THỰC

VỚI TRUY VẤN LỒNG

2.1 PostgreSQL và khung nhìn thực trong PostgreSQL

PostgreSQL là một hệ quản trị cơ sở dữ liệu (HQT CSDL)

mã nguồn mở PostgreSQL đã tạo được lòng tin về độ tin cậy cũng như tính đúng đắn, toàn vẹn dữ liệu, được bộ thông tin và truyền thông khuyến cáo sử dụng

Là một HQT CSDL mã nguồn mở hàng đầu trên thế giới và KNT đã được triển khai trên PostgreSQL ở các phiên bản 9.3.4, 9.4, 10… KNT là tính năng bảng ảo tiện lợi khác đã được hỗ trợ bởi PostgreSQL KNT cũng có thể được đánh chỉ mục, không giống các views thông thường được tạo ra mỗi lần chúng được gọi, KNT là các ảnh chụp tại một thời điểm Chúng không được làm mới (refreshed) ngoại trừ được chỉ định Điều này có thể tăng đáng kể tốc độ với các truy vấn chạy sử dụng KNT Tuy nhiên KNT trong PostgreSQL vẫn chưa hỗ trợ vấn đề cập nhật đồng bộ gia tăng Do vậy, việc nghiên cứu các kỹ thuật CNGT cho KNT trên PostgesSQL đang rất được quan tâm

2.2 Các phương pháp cập nhật KNT

2.2.1 Phương pháp làm mới KNT

Việc triển khai KNT cho HQT CSDL PostgreSQL chỉ mới được đưa vào ở phiên bản 10 và việc cập nhật được thực hiện

thông qua lệnh refresh materialized view Điều này tốn chi phí

xấp xỉ chi phí thực hiện truy vấn, và không đảm bảo được dữ liệu trên KNT luôn luôn là mới nhất Bất cứ khi nào người dùng truy cập dữ liệu của KNT chỉ có thể thấy được dữ liệu ở lần cập nhật gần nhất, không phải ở thời điểm hiện tại Người dùng vẫn phải

cập nhật bằng lệnh refresh materialized view, tùy thuộc vào người

quản trị hệ thống và nhu cầu sử dụng dữ liệu Phương pháp này không hiệu quả, đặc biệt khi dữ liệu trong KNT yêu cầu tính chính xác tại mọi thời điểm

2.2.2 Phương pháp cập nhật gia tăng đồng bộ

Cập nhật gia tăng là kỹ thuật cập nhật dữ liệu trên KNT một cách đồng bộ, được thực hiện mỗi khi dữ liệu tại các BG tham gia

Trang 13

vào KNT có sự thay đổi, nhờ đó giúp cho KNT luôn trong trạng thái được cập nhật Việc CNGT KNT có thể được thực hiện thông qua việc xây dựng các trigger bắt các sự kiện làm thay đổi dữ liệu trên các BG, từ đó xác định các thay đổi có thể làm ảnh hưởng đến tính đúng đắn của kết quả được lưu trong KNT, sau đó tiến hành việc cập nhật dữ liệu trong KNT Có thể xem thao tác CNGT là một phần trong giao tác thay đổi dữ liệu trên các BG Nghiên cứu đề xuất tạo KNT như một bảng (table), sau đó sử dụng hệ thống các trigger cài đặt trên các BG bắt sự kiện thay đổi

dữ liệu, từ đó cập nhật vào KNT những thay đổi liên quan

2.2.3 Một số vấn đề cần quan tâm khi CNGT KNT với truy vấn lồng

Để quá trình CNGT được tối ưu, ta phải quan tâm đến vấn đề sàng lọc dữ liệu Chỉ những dữ liệu nào liên quan trực tiếp đến KNT và ảnh hưởng đến tính đúng đắn của dữ liệu trong KNT mới cần được cập nhật Điều này có thể được thực hiện thông qua việc phân tích các mệnh đề JOIN, WHERE, FROM để đưa ra điều kiện sàng lọc dữ liệu Mỗi khi thao tác dữ liệu xảy ra trên BG, thông qua điều kiện lọc, ta có thể xác định được dữ liệu đang được xử lý có ảnh hưởng đến KNT hay không, từ đấy đưa ra quyết định tiếp tục thực thi phần mã CNGT hay thoát khỏi hàm trigger Thứ hai, ta phải quan tâm đến các phép nối trong truy vấn Khi một KNT được tạo ra trên cơ sở truy vấn bao gồm nhiều phép nối giữa các bảng với nhau, quá trình CNGT cần chắc chắn

dữ liệu trên KNT luôn đảm bảo tính toàn vẹn, ràng buộc giữa các bảng khi một trong số các BG có sự thay đổi

2.3 Thuật toán cập nhật gia tăng KNT với truy vấn lồng

2.3.1 Thuật toán chuyển từ truy vấn lồng sang truy vấn nối trong

Một TVG có dạng (chỉ áp dụng 2 bảng và trường hợp IN): SELECT <danh sách cột>

FROM <table_1>INNER JOIN<table_2> ON <điều kiện nối> WHERE <so sánh tập hợp> (SELECT <danh sách cột>

FROM < danh sách các bảng> WHERE<điều kiện nối>)

Bước 1: Gọi tập các trường chứa trong mệnh đề lần lượt là:

Ngày đăng: 09/05/2022, 01:15

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w