BigQuery 7 — Bảo mật, BigQuery ML & vận hành
BigQuery 7 — Bảo mật, BigQuery ML & vận hành
Đây là bài khép lại series BigQuery chuyên sâu. Sáu bài trước xoay quanh câu hỏi "làm sao truy vấn nhanh và rẻ" — từ tổng quan kiến trúc, lưu trữ, cú pháp, partitioning & clustering cho đến chi phí & hiệu năng. Bài này trả lời ba câu hỏi còn lại mà bất kỳ hệ thống dữ liệu ngân hàng nào cũng phải trả lời trước khi lên production: Ai được xem gì? (bảo mật) — Làm được gì thông minh hơn trên chính dữ liệu đó? (BigQuery ML) — Làm sao biết hệ thống đang chạy ra sao và ai đang đốt tiền? (vận hành).
Với môi trường ngân hàng, phần bảo mật không phải "nice to have" — nó là điều kiện cần để dữ liệu khách hàng được phép đặt lên nền tảng cloud.
Mô hình phân quyền: IAM của BigQuery
BigQuery không có hệ thống user/password riêng như PostgreSQL. Mọi quyền truy cập đi qua Google Cloud IAM — cùng một hệ phân quyền dùng cho toàn bộ Google Cloud. Nguyên tắc cốt lõi: bạn gán role (vai trò, là một tập hợp permission) cho principal (người dùng, group, hoặc service account) tại một resource ở một cấp nào đó trong cây tài nguyên.
Cây tài nguyên có tính kế thừa từ trên xuống: quyền cấp ở tầng cao hơn tự động áp xuống các tầng dưới.
Các role phổ biến bạn sẽ dùng gần như mỗi ngày:
roles/bigquery.dataViewer— đọc dữ liệu (metadata + nội dung bảng), không sửa, không chạy job tính tiền của riêng mình. Gán ở cấp dataset để chỉ mở đúng một tập dữ liệu.roles/bigquery.dataEditor— đọc + tạo/sửa/xoá bảng trong dataset. Dành cho pipeline nạp dữ liệu.roles/bigquery.jobUser— được chạy job (query, load, export) và chịu chi phí trên project đó. Đây là điểm hay gây bối rối:dataViewercho phép thấy dữ liệu nhưng bạn vẫn cầnjobUserđể chạy một câu SELECT. Một analyst điển hình cần cả hai:dataViewertrên dataset +jobUsertrên project.roles/bigquery.admin— toàn quyền. Chỉ dành cho một nhóm rất nhỏ.
Least privilege (đặc quyền tối thiểu) là kim chỉ nam: gán quyền ở cấp thấp nhất đủ dùng. Đừng cho dataViewer ở cấp project nếu người đó chỉ cần một dataset; đừng cho admin khi dataEditor là đủ.
Service account là "người dùng máy" dành cho tự động hoá — pipeline Airflow, Cloud Function, Dataflow job đều chạy dưới danh nghĩa một service account với đúng bộ quyền tối thiểu, thay vì chạy dưới tài khoản cá nhân của một kỹ sư. Nguyên tắc: một service account cho một trách nhiệm, để khi audit log ghi lại một job, bạn biết chính xác pipeline nào đã chạy.
Authorized views: chia sẻ dữ liệu mà không mở bảng gốc
Đây là một trong những cơ chế governance đắt giá nhất của BigQuery và rất dễ hiểu sai. Vấn đề: bạn có bảng transactions chứa cột nhạy cảm, và một nhóm analyst chỉ cần xem một tập con đã lọc/che của nó. Nếu bạn gán dataViewer trên bảng gốc, họ thấy tất cả.
Authorized view giải bài toán này: bạn tạo một view chứa đúng logic lọc/che cần thiết, rồi "authorize" (uỷ quyền) cho view đó được đọc bảng nguồn. Kết quả: user chỉ cần quyền trên view, hoàn toàn không cần quyền trên bảng gốc. View đọc bảng "thay mặt" user.
-- (minh hoạ — BigQuery)
-- 1) View đã lọc + che: chỉ giao dịch >= 2025, ẩn số CIF đầy đủ
CREATE VIEW `bank.shared_views.tx_safe` AS
SELECT
txn_id,
txn_date,
branch_code,
amount,
CONCAT('****', RIGHT(cif_number, 4)) AS cif_last4 -- che bớt định danh
FROM `bank.retail_banking.transactions`
WHERE txn_date >= '2025-01-01';
-- 2) Uỷ quyền cho view được đọc dataset nguồn (chạy bởi admin của bảng gốc).
-- Sau bước này, cấp cho analyst quyền dataViewer TRÊN dataset shared_views,
-- KHÔNG cấp quyền gì trên retail_banking.
Cùng ý tưởng đó, BigQuery còn có authorized dataset (uỷ quyền cả một dataset thay vì từng view) và authorized routine (uỷ quyền cho một UDF/stored procedure được đọc bảng nguồn) — tiện khi số lượng view lớn. Mô hình chung là: lớp trung gian có quyền, người dùng cuối chỉ nói chuyện với lớp trung gian.
Column-level & row-level security
Authorized view là công cụ mạnh nhưng thủ công. Với dữ liệu ngân hàng, BigQuery còn cung cấp hai cơ chế khai báo ở ngay tầng bảng.
Column-level security (bảo mật cấp cột)
Bạn gắn policy tag (thẻ chính sách) lên từng cột nhạy cảm. Policy tag được tổ chức trong một taxonomy (cây phân loại) quản lý qua Dataplex. Ai không có quyền "Fine-Grained Reader" trên tag đó sẽ không đọc được cột, dù họ có quyền trên bảng. Ví dụ: gắn tag PII/high lên cột national_id, phone — chỉ nhóm compliance đọc được, analyst thường query bảng vẫn chạy nhưng các cột đó bị chặn.
Đi kèm là data masking (che dữ liệu): thay vì chặn hẳn, bạn cho phép người dùng thấy giá trị đã bị biến đổi — hash, che một phần, hoặc trả NULL — tuỳ theo quyền của họ trên policy tag. Cùng một cột salary, người có quyền thấy số thật, người không có quyền thấy giá trị đã hash.
Row-level security (bảo mật cấp hàng — RLS)
Đây là cơ chế lọc theo dòng dựa trên danh tính người chạy query. Bạn tạo row access policy: mỗi policy giống một mệnh đề WHERE được áp ngầm và bắt buộc cho một nhóm principal.
-- (minh hoạ — BigQuery)
-- Analyst chi nhánh Hà Nội chỉ thấy giao dịch của branch_code = 'HN01'
CREATE ROW ACCESS POLICY rls_branch_hn
ON `bank.retail_banking.transactions`
GRANT TO ('group:[email protected]')
FILTER USING (branch_code = 'HN01');
-- Nhóm HQ thấy tất cả (filter luôn đúng)
CREATE ROW ACCESS POLICY rls_hq_all
ON `bank.retail_banking.transactions`
GRANT TO ('group:[email protected]')
FILTER USING (TRUE);
FILTER USING (...) hoạt động đúng như một WHERE: chỉ những dòng khớp mới hiển thị cho principal trong GRANT TO. Một FILTER USING (TRUE) mở tất cả các dòng (hữu ích khi mới triển khai, giữ quyền cũ không đứt); FILTER USING (FALSE) chặn tất cả. Người không nằm trong bất kỳ policy nào của bảng sẽ không thấy dòng nào.
Một mẫu rất mạnh là dùng hàm SESSION_USER() — trả về email người đang chạy query — để lọc động mà không cần một policy cho mỗi người:
-- (minh hoạ — BigQuery)
-- Bảng có cột owner_email; mỗi người chỉ thấy dòng của chính mình
CREATE ROW ACCESS POLICY rls_own_rows
ON `bank.risk_analytics.case_notes`
GRANT TO ('domain:bank.com')
FILTER USING (owner_email = SESSION_USER());
Vài giới hạn cần nhớ (theo tài liệu Google): RLS chỉ chạy với GoogleSQL (không dùng được Legacy SQL); không áp được lên cột JSON, bảng tạm hay truy vấn wildcard; và một thao tác WRITE_TRUNCATE sẽ xoá ngầm toàn bộ row access policy của bảng — pipeline overwrite bảng phải tạo lại policy sau đó, đây là bẫy vận hành kinh điển.
So sánh với các hệ khác
Ý tưởng RLS không mới. Nếu bạn đến từ Postgres concurrency & MVCC thì Postgres có CREATE POLICY ... USING (...) sau khi bật ALTER TABLE ... ENABLE ROW LEVEL SECURITY — cùng tinh thần "policy = WHERE ngầm theo user". Còn ở tầng BI, Looker governance đạt hiệu quả tương tự bằng access_filter gắn user attribute — nhưng đó là lọc ở tầng công cụ BI, người có quyền query bảng gốc vẫn thấy tất cả. Khác biệt bản chất: RLS của BigQuery lọc tại tầng dữ liệu, nên áp cho mọi đường vào (SQL trực tiếp, API, BI tool) chứ không riêng một công cụ. Với ngân hàng, lọc ở tầng dữ liệu là nơi đáng tin cậy nhất để đặt ranh giới chi nhánh.
Mã hoá & tuân thủ
Đây là phần khiến bộ phận compliance của ngân hàng gật đầu:
- Mã hoá mặc định: mọi dữ liệu trên BigQuery được mã hoá at-rest và in-transit tự động, không cần cấu hình. Google quản lý khoá.
- CMEK (Customer-Managed Encryption Keys): nếu chính sách yêu cầu ngân hàng tự nắm khoá, bạn dùng khoá quản lý trong Cloud KMS. Bạn có thể thu hồi khoá để vô hiệu hoá truy cập dữ liệu — một yêu cầu tuân thủ thường gặp.
- VPC Service Controls: dựng "vành đai" (perimeter) quanh dữ liệu để chống rò rỉ ra ngoài — chặn việc export/copy dữ liệu sang project ngoài vành đai, kể cả khi ai đó có credential hợp lệ.
- Audit logs (Cloud Audit Logs): ghi lại ai đã chạy gì, khi nào — Admin Activity và Data Access log. Không thể tắt Admin Activity log; đây là bằng chứng cho kiểm toán.
- Data residency: BigQuery gắn dữ liệu với region/multi-region bạn chọn khi tạo dataset và không tự di chuyển ra ngoài. Với ngân hàng có yêu cầu dữ liệu phải nằm trong nước, chọn đúng region là quyết định bắt buộc ngay từ đầu (thường không đổi được sau này).
BigQuery ML: huấn luyện mô hình bằng SQL
BigQuery ML (BQML) cho phép huấn luyện và dùng mô hình machine learning ngay bằng SQL, trên chính dữ liệu đang nằm trong warehouse — không phải export ra ngoài, không phải dựng cụm Spark/Python riêng. Với một analyst đã thạo SQL, đây là cửa ngõ vào ML mà không cần đổi ngôn ngữ.
Cú pháp trung tâm là CREATE MODEL ... OPTIONS(model_type=...) AS SELECT: câu SELECT ở cuối chính là tập huấn luyện, trong đó một cột được đặt tên (hoặc chỉ định) là label (nhãn cần dự báo), các cột còn lại là feature.
Các loại mô hình chính (theo tài liệu Google):
linear_reg— hồi quy tuyến tính, dự báo giá trị liên tục (vd: dự báo doanh số).logistic_reg— phân loại nhị phân (vd: khách có churn hay không, giao dịch có gian lận hay không).kmeans— phân cụm không giám sát (vd: phân khúc khách hàng).arima_plus— dự báo chuỗi thời gian (vd: dự báo lượng giao dịch theo ngày), dùng vớiML.FORECAST.boosted_tree_classifier/ regressor — cây tăng cường (XGBoost), thường mạnh nhất cho dữ liệu bảng.dnn— mạng nơ-ron sâu.- Remote model — BQML không tự huấn luyện, mà gọi ra một endpoint bên ngoài: một mô hình đã deploy trên Vertex AI, hoặc một LLM (vd Gemini) để làm sinh văn bản/phân loại text ngay trong SQL. Đây là cầu nối giữa warehouse và LLM — bạn
SELECTra prompt và nhận kết quả về như một cột.
Vòng đời điển hình: train → evaluate → predict.
-- (minh hoạ — BigQuery)
-- 1) TRAIN: dự báo churn (logistic regression). Cột `churned` là label.
CREATE OR REPLACE MODEL `bank.risk_analytics.churn_model`
OPTIONS(
model_type = 'logistic_reg',
input_label_cols = ['churned']
) AS
SELECT
churned, -- label: 1 = rời bỏ, 0 = còn ở lại
tenure_months,
num_products,
avg_balance_3m,
txn_count_30d,
is_salary_account
FROM `bank.risk_analytics.customer_features`
WHERE snapshot_date = '2026-05-31';
-- 2) EVALUATE: xem precision, recall, roc_auc, log_loss...
SELECT *
FROM ML.EVALUATE(MODEL `bank.risk_analytics.churn_model`);
-- 3) PREDICT: chấm điểm khách hàng hiện tại
SELECT
customer_id,
predicted_churned, -- nhãn dự báo (0/1)
predicted_churned_probs -- xác suất cho từng lớp
FROM ML.PREDICT(
MODEL `bank.risk_analytics.churn_model`,
(SELECT * FROM `bank.risk_analytics.customer_features`
WHERE snapshot_date = '2026-06-30')
);
Với chuỗi thời gian, dùng ML.FORECAST(MODEL ..., STRUCT(30 AS horizon)) trên một mô hình arima_plus để dự báo 30 kỳ tới.
Ưu điểm: dữ liệu không phải di chuyển (an toàn + rẻ, tránh chi phí export); analyst SQL tự làm được ML cơ bản mà không cần đội ML riêng; mô hình sống ngay cạnh dữ liệu nên retrain dễ (chỉ là chạy lại một câu SQL, có thể đặt lịch — xem phần scheduled queries). Giới hạn: không thay thế được ML "custom" phức tạp (kiến trúc mạng đặc thù, feature engineering nặng, mô hình vision/NLP lớn); khả năng tuning và kiểm soát kém hơn framework chuyên dụng; huấn luyện cũng tính tiền theo byte/slot như query thường nên mô hình lớn trên dữ liệu lớn không hề rẻ. Quy tắc thực dụng: BQML để prototype nhanh và cho các bài toán bảng phổ biến; chuyển sang Vertex AI khi cần độ phức tạp hoặc kiểm soát cao hơn.
Tích hợp hệ sinh thái
- Looker & BI Engine: kết quả BQML (bảng dự báo) là một bảng bình thường, nối thẳng vào Looker để dựng dashboard; BI Engine cache trong bộ nhớ giúp dashboard phản hồi tức thì.
- Vertex AI: nơi deploy/host mô hình phức tạp; BQML gọi ngược lại qua remote model, tạo vòng khép kín.
- Notebooks & export: BigQuery kết nối trực tiếp với Jupyter/Colab; hoặc export bảng/dự báo ra GCS cho các hệ khác dùng.
Vận hành & giám sát
Khi hệ thống chạy production, câu hỏi thường trực là: truy vấn nào tốn nhất, ai chạy, chậm ở đâu? BigQuery trả lời qua INFORMATION_SCHEMA — một bộ view hệ thống truy vấn được bằng chính SQL.
Đáng chú ý nhất là INFORMATION_SCHEMA.JOBS — nhật ký mọi job, với các cột then chốt: job_id, user_email (ai chạy), total_bytes_billed (byte bị tính tiền), total_slot_ms (slot đã tiêu — thước đo "công" tính toán), creation_time, query, job_type, state.
-- (minh hoạ — BigQuery)
-- Top 10 truy vấn tốn tiền nhất trong 7 ngày qua (region US)
SELECT
user_email,
job_id,
ROUND(total_bytes_billed / POW(1024, 4), 3) AS tb_billed, -- ~ để ước tiền
total_slot_ms,
creation_time,
SUBSTR(query, 0, 120) AS query_preview
FROM `region-us`.INFORMATION_SCHEMA.JOBS
WHERE job_type = 'QUERY'
AND state = 'DONE'
AND creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
ORDER BY total_bytes_billed DESC
LIMIT 10;
Các view khác hay dùng: TABLES/COLUMNS (metadata schema), TABLE_STORAGE (dung lượng lưu trữ để tối ưu chi phí storage), SCHEMATA (danh sách dataset). Đây là cách tự động hoá audit: một scheduled query mỗi sáng quét JOBS và cảnh báo nếu ai đó vừa quét vài TB.
Các trụ cột vận hành còn lại:
- Quotas & reservations: mô hình on-demand trả theo byte quét (linh hoạt, xem Chi phí & hiệu năng); reservations mua trước một lượng slot cố định (chi phí ổn định, phù hợp workload lớn/đều). Ngân hàng thường trộn cả hai: reservation cho pipeline ETL định kỳ, on-demand cho query ad-hoc.
- Scheduled queries: đặt lịch chạy SQL định kỳ (nạp bảng tổng hợp mỗi đêm, retrain mô hình BQML mỗi tuần) — thay cho một cron/Airflow đơn giản.
- Job monitoring: ngoài
INFORMATION_SCHEMA, có bảng điều khiển hành chính (Admin Resource Charts) theo dõi slot usage theo thời gian để phát hiện tắc nghẽn. - Cost attribution bằng labels: gắn label (vd
team:risk,env:prod,pipeline:churn) lên job/dataset, rồi groupINFORMATION_SCHEMA.JOBStheo label để biết đội nào tốn bao nhiêu — nền tảng của showback/chargeback nội bộ (nối tiếp bài Chi phí & hiệu năng).
Use case thực tế: siết quyền theo chi nhánh + dự báo churn
Bài toán tại một ngân hàng bán lẻ: bảng transactions dùng chung cho toàn hệ thống, nhưng analyst mỗi chi nhánh chỉ được xem giao dịch của chi nhánh mình, còn Hội sở xem toàn bộ. Đồng thời, đội Rủi ro muốn dự báo khách hàng có nguy cơ rời bỏ để chăm sóc sớm.
Bước 1 — Phân quyền nền: analyst được dataViewer trên dataset + jobUser trên project. Pipeline nạp dữ liệu chạy bằng service account riêng có dataEditor.
Bước 2 — Ranh giới chi nhánh bằng RLS: thay vì nhân bản bảng cho từng chi nhánh (tốn kém, dễ lệch), tạo một ROW ACCESS POLICY cho mỗi group chi nhánh với FILTER USING (branch_code = '...'), và một policy FILTER USING (TRUE) cho group Hội sở. Từ giờ, cùng một câu SELECT * FROM transactions, analyst HN thấy dữ liệu HN, analyst SG thấy dữ liệu SG — ranh giới nằm ở tầng dữ liệu, áp cho cả query trực tiếp lẫn dashboard Looker.
Bước 3 — Che PII bằng column-level security: gắn policy tag PII/high lên national_id, phone; chỉ compliance đọc giá trị thật, analyst thấy dạng masked.
Bước 4 — Dự báo churn bằng BQML: một scheduled query mỗi tuần chạy CREATE OR REPLACE MODEL ... logistic_reg trên bảng feature (bảng này đã được RLS lọc theo chi nhánh, nên mô hình mỗi đội huấn luyện trên đúng phạm vi của mình), rồi ML.PREDICT để ra danh sách khách hàng nguy cơ cao. Kết quả đổ vào một bảng, nối lên Looker cho đội chăm sóc.
Bước 5 — Giám sát: một scheduled query đọc INFORMATION_SCHEMA.JOBS, group theo label team, gửi báo cáo byte-billed hằng ngày. Kết hợp audit log để truy vết truy cập dữ liệu nhạy cảm.
Kết quả: một bảng duy nhất, một mô hình duy nhất về quyền, dữ liệu nhạy cảm được che, ML chạy ngay tại chỗ, và chi phí minh bạch theo đội — tất cả bằng SQL và cấu hình, không cần hệ thống rời rạc bên ngoài.
Ghi nhớ
- IAM là cổng duy nhất. Gán role ở cấp thấp nhất đủ dùng (least privilege); analyst cần
dataViewer+jobUser; tự động hoá dùng service account riêng theo trách nhiệm. - Authorized view/dataset/routine cho phép chia sẻ dữ liệu đã lọc/che mà user không cần quyền trên bảng gốc — lớp trung gian có quyền, người dùng chỉ thấy view.
- Column-level security (policy tag qua Dataplex) + masking che cột nhạy cảm; row-level security (
CREATE ROW ACCESS POLICY ... FILTER USING) lọc dòng theo danh tính — lý tưởng cho ranh giới chi nhánh. Nhớ:WRITE_TRUNCATExoá ngầm mọi row access policy. - Tuân thủ: mã hoá mặc định, CMEK khi cần tự nắm khoá, VPC Service Controls chống rò rỉ, audit logs cho kiểm toán, chọn đúng region cho data residency ngay từ đầu.
- BQML = ML bằng SQL:
CREATE MODEL→ML.EVALUATE→ML.PREDICT/ML.FORECAST; đủ loại từ hồi quy, k-means, ARIMA_PLUS, boosted tree đến remote model gọi Vertex/LLM. Mạnh cho prototype & bài toán bảng; chuyển Vertex AI khi cần phức tạp. - Vận hành:
INFORMATION_SCHEMA.JOBSđể soi chi phí/hiệu năng/ai chạy; reservations vs on-demand; scheduled queries để tự động; labels để quy chi phí theo đội.
Đọc tiếp
- BigQuery 1 — Tổng quan: kiến trúc nền tảng của toàn series.
- BigQuery 4 — Partitioning & clustering: thiết kế bảng để RLS/BQML chạy trên dữ liệu đã tối ưu.
- BigQuery 5 — Chi phí & hiệu năng: dry run, byte quét, slot, và cost attribution bằng labels.
- Looker 7 — Governance & deploy:
access_filterở tầng BI, đối chiếu với RLS tầng dữ liệu. - LLM 1 — Tổng quan: nền tảng cho remote model gọi LLM ngay trong SQL.
Bài viết liên quan
Cách index hoạt động (B-Tree), đọc EXPLAIN, seq scan vs index scan và mẫu tối ưu truy vấn.
Khoá, ràng buộc, quan hệ và chuẩn hoá 1NF/2NF/3NF — thiết kế lược đồ đúng từ đầu.
Kết nhiều bảng đúng cách: các loại JOIN, bẫy thường gặp và phép hợp tập.
Truy vấn lồng, CTE (WITH), CTE đệ quy và hàm cửa sổ — vũ khí cho phân tích nâng cao.