Logo Wecommit
Về chúng tôiCộng đồngLời chứng thựcTài nguyên
Logo Wecommit

Oracle vs SQL Server: 6 khác biệt thật khi làm dự án lớn

Oracle vs SQL Server khác nhau ở đâu khi chạy hệ thống giao dịch lớn: MVCC, leo thang lock, partition, AWR, Flashback và tiền license. Có demo thật.

Hơn 11 năm tôi làm dự án database, có một câu hỏi cứ quay lại: tại sao core banking, core chứng khoán, core billing viễn thông ở Việt Nam gần như luôn chạy Oracle chứ không phải SQL Server? Đa số trả lời "vì Oracle nó ngon hơn". Hỏi ngon hơn ở chỗ nào thì tắc.

Bài này so sánh Oracle vs SQL Server bằng nguyên lý. Sáu khác biệt, mỗi cái có demo chạy thật trên cả hai bên, kèm cấu hình để anh em chép về tự dựng lại.

Bài viết đi theo đúng thứ tự video, bổ sung phần dẫn nguồn gốc từ tài liệu Oracle và Microsoft Learn, cộng thêm mục "Giới hạn thật" mà video chưa nói tới.

Sáu khác biệt đó là gì?

Đây là bảng gói cả bài. Anh em đọc bảng này trước rồi hãy đi vào từng mục.

#Chỗ khác biệtOracleSQL Server
1Đọc trong lúc có người ghiKhông chờ, lấy bản cũ trong UNDOMặc định là chờ, phải bật cơ chế mới hết chờ
2Chỗ chứa dữ liệu trước thay đổiUNDO tablespace, thiết kế riêngtempdb, dùng chung với sort và hash join
3Leo thang lockKhông cóCó, khoá cả bảng khi vượt ngưỡng
4Chia nhỏ bảngPartition và subpartitionPartition, không có subpartition
5Chạy song songPARALLEL cho cả SELECT và DMLChủ yếu cho SELECT
6Soi hiệu năng và cứu sự cốAWR và FlashbackQuery Store, khôi phục từ backup

Vì sao câu SELECT trên SQL Server bị treo mà trên Oracle thì không?

Vì mặc định của hai ông khác nhau. Oracle cho câu đọc lấy bản dữ liệu cũ nên nó chạy ngay. SQL Server mặc định bắt câu đọc chờ câu ghi commit xong.

Tôi lấy đúng ví dụ trong video. Một cặp vợ chồng chung tài khoản 1000 đô. Người vợ rút 100 đô, đã update nhưng chưa commit. Cùng lúc người chồng chạy một câu SELECT lên đúng bản ghi ấy. Kết quả ra 900 hay 1000?

Phải là 1000. Bà vợ hoàn toàn có thể rollback. Trả ra 900 là sai dữ liệu. Cả hai ông đều hiểu điều đó, nhưng cách đối phó thì ngược nhau.

Oracle xử lý thế nào?

Oracle trả kết quả ngay, và trả giá trị cũ. Gõ lệnh một phát là có số.

Hai phiên Oracle trên Toad: phiên bên trái đang update chưa commit, phiên bên phải chạy select vẫn trả về giá trị cũ A1 ngay lập tức

Bảng demo là WECOMMITDEMO, 10.000 bản ghi, hai cột IDVALUE chạy từ A1 tới A10000. Phiên trái update ID = 1 thành 'B1' rồi để treo. Phiên phải select đúng bản ghi đó, ra A1, ra ngay, không chờ giây nào.

Tài liệu Oracle Database Concepts gọi thẳng tên đặc tính này là nonblocking queries: "Readers and writers of data do not block one another". Bản cũ mà câu đọc lấy về nằm trong UNDO.

SQL Server xử lý thế nào?

SQL Server mặc định chạy ở isolation level READ COMMITTED không dùng row versioning. Câu đọc xin shared lock, mà bản ghi đang bị khoá ghi, nên nó đứng chờ.

Chờ đến bao giờ? Đến khi ông kia commit hoặc rollback. Ông kia không quyết thì nó treo mãi. Treo mãi thật.

Anh em nào từng nghe lập trình viên kêu "hệ thống em hay bị treo, hay bị lock" thì phần lớn là dính đúng mặc định này. Một câu update thì chưa thấy gì. Nhưng hàng nghìn giao dịch cùng lúc thì câu SELECT xếp hàng đợi, hệ thống chậm lòi mắt ngay.

Bật READ_COMMITTED_SNAPSHOT là xong chuyện chưa?

Chưa xong hẳn, nhưng đây là việc đầu tiên phải làm. SQL Server chuyển được sang cơ chế giống Oracle, chỉ là nó không bật sẵn.

Cửa sổ SSMS chạy lệnh ALTER DATABASE wecommit SET READ_COMMITTED_SNAPSHOT ON và báo Commands completed successfully

Đây là đúng bộ lệnh tôi chạy trong video. Anh em chép về dùng luôn.

-- Xem isolation level hien tai cua phien
DBCC USEROPTIONS;

-- Bat row versioning cho read committed
-- Luu y: chi con dung MOT ket noi toi database nay khi chay lenh
ALTER DATABASE wecommit
SET READ_COMMITTED_SNAPSHOT ON;

-- Kiem tra lai
SELECT name, is_read_committed_snapshot_on
FROM sys.databases
WHERE name = 'wecommit';

Bật xong chạy lại đúng demo cũ thì hành vi giống hệt Oracle. Câu update vẫn treo đấy, câu select vẫn ra giá trị cũ, và nó ra ngay.

Microsoft Learn ghi rõ: khi READ_COMMITTED_SNAPSHOT bật ON, engine dùng row versioning để dựng ảnh chụp nhất quán cho từng câu lệnh, và không dùng lock để chặn câu ghi. Tính năng này có từ SQL Server 2005. Oracle có cơ chế tương đương trước đó nhiều năm. Đấy là một trong các lý do ngân hàng thời trước ưu tiên Oracle.

UNDO của Oracle khác tempdb của SQL Server ở chỗ nào?

Khác ở chỗ một bên là kho chuyên dụng, một bên là kho dùng chung. Tư tưởng hai ông giống nhau: vứt bản cũ ra chỗ khác. Nhưng cái chỗ khác ấy mới là chuyện.

Sơ đồ anh Huy vẽ tay: Oracle đẩy dữ liệu cũ sang UNDO, SQL Server đẩy sang tempdb vốn dùng chung với sort, hash join và temp table

Oracle dựng hẳn một UNDO tablespace riêng, chỉ chứa dữ liệu trước thay đổi của các câu DML, không chung đụng với thứ gì khác. SQL Server vứt version store vào tempdb, mà tempdb là kho dùng chung của cả instance. Nó còn phải gánh:

  • Dữ liệu tạm để sắp xếp khi câu lệnh có ORDER BY
  • Vùng làm việc của hash join
  • Toàn bộ temporary table anh em tạo ra

Điều đó dẫn tới đâu? tempdb chậm thì một loạt thứ chậm theo. Một bên là khu nhà đặc chủng, một bên là kho chứa hổ lốn.

Việc làm được ngay cho anh em đang chạy SQL Server production: chuyển tempdb sang phân vùng đọc ghi nhanh nhất mà anh em có. Riêng việc đó thôi đã cải thiện được nhiều.

PostgreSQL cũng đi theo MVCC, nhưng giữ bản cũ ngay trong bảng nên sinh ra bài toán dọn rác khác hẳn. Tôi có phân tích riêng ở bài Vacuum trong PostgreSQL ảnh hưởng tới hiệu năng thế nào.

Leo thang lock là gì và vì sao nó giết hệ thống giao dịch cao?

Leo thang lock là khi database gom nhiều khoá dòng thành một khoá cả bảng, để đỡ tốn tài nguyên quản lý khoá. Cái giá phải trả là những dòng chẳng liên quan gì cũng chết oan.

Anh em hình dung. Bảng 5.000 dòng, một giao dịch update 4.999 dòng, còn đúng một dòng không ai đụng vào. Về nguyên tắc người khác vẫn phải sửa được dòng đó chứ, đúng không ạ? Không. Database leo thang lock thì nó khoá luôn cả bảng. Dòng cuối cùng kia tèo theo.

Demo trên SQL Server

Vẫn bảng WECOMMITDEMO 10.000 bản ghi. Phiên thứ nhất update 8.000 dòng đầu, chưa commit. Phiên thứ hai chỉ update duy nhất ID = 10000, chẳng liên quan gì tới 8.000 dòng kia.

SSMS phiên thứ hai chỉ update một dòng ID bằng 10000 nhưng tab vẫn báo Executing vì cả bảng đã bị khoá

Nó chờ. Tab vẫn quay Executing. Một câu update đúng một dòng, không đụng vào ai, mà vẫn bị chặn. Vì sao? Vì 8.000 khoá dòng đã bị chuyển thành một khoá cả bảng.

Chỗ này tài liệu Microsoft nói ra con số rất cụ thể, khớp đúng với thứ trên màn hình. Ngưỡng kích hoạt leo thang lock là 5.000 khoá trên một lần tham chiếu tới một bảng hoặc một index. Tài liệu cũng ghi rõ engine không leo từ khoá dòng lên khoá trang, mà leo thẳng lên khoá bảng. 8.000 vượt ngưỡng 5.000. Thế là cả bảng bị khoá.

Demo trên Oracle

Cùng kịch bản đó. Phiên trái update ID BETWEEN 1 AND 8000. Phiên phải update ID = 10000.

Hai phiên Oracle: một phiên update 8000 dòng, phiên kia update dòng ID 10000, cả hai đều chạy xong không phiên nào bị chờ

Cả hai chạy xong bình thường. Không ông nào bị lock.

Oracle không có chuyện leo thang lock. Bảng 100 triệu bản ghi, anh em update 99 triệu dòng, thì một dòng còn lại vẫn không bị khoá. Ông khác vào xử lý dòng đó ngon lành. Đây là chỗ ăn tiền, và với ngân hàng thì nó ăn tiền thật.

Nhìn hời hợt thì hai ông đều gọi là lock cả. Đi sâu vào thì theo góc nhìn của tôi là hai câu chuyện khác hẳn nhau.

Ba thứ quyết định một câu lệnh chạy nhanh hay chậm?

Khi tôi phân tích hiệu năng một câu lệnh, tôi luôn đi vào chiến lược thực thi. Gốc nằm ở đó. Và có ba chỗ hai ông này lệch nhau rõ: partition, index, parallel. Anh em chưa nắm phần nền thì đọc bài Tối ưu SQL nên bắt đầu từ đâu trước.

Partition và subpartition khác nhau ra sao?

Partition là chia một bảng to thành nhiều phần theo một cột. Subpartition là chia tiếp mỗi phần đó theo cột thứ hai. Oracle có cả hai. SQL Server chỉ có tầng thứ nhất.

Sơ đồ partition và subpartition cho bảng TX History 100 triệu bản ghi, chia theo TXDATE rồi chia tiếp theo chi nhánh

Tôi ví dụ bằng thứ gặp hàng ngày. Bảng TRANSACTION_HISTORY của một ngân hàng, khoảng 100 triệu bản ghi. Người dùng hay tra lịch sử giao dịch trong một khoảng ngày. Chia partition theo TRANSACTION_DATE theo tháng thì hệ thống chỉ tìm trong đúng vùng tháng đó, thay vì quét loạn xạ khắp nơi.

Nhưng thực tế người ta còn lọc thêm chi nhánh. Lúc này Oracle chia tiếp bằng subpartition, vùng phải tìm co nhỏ thêm lần nữa. Tài liệu Oracle VLDB and Partitioning Guide gọi cái này là composite partitioning, có sẵn dạng range-list đúng như ví dụ trên.

-- Oracle: partition theo ngay giao dich, subpartition theo chi nhanh
CREATE TABLE transaction_history
  ( txn_id     NUMBER,
    txn_date   DATE,
    branch     VARCHAR2(20),
    txn_amount NUMBER )
PARTITION BY RANGE (txn_date)
SUBPARTITION BY LIST (branch)
SUBPARTITION TEMPLATE
  ( SUBPARTITION sp_hanoi VALUES ('HANOI'),
    SUBPARTITION sp_hcm   VALUES ('HCM'),
    SUBPARTITION sp_khac  VALUES (DEFAULT) )
( PARTITION p_2026_01 VALUES LESS THAN (TO_DATE('01-02-2026','DD-MM-YYYY')),
  PARTITION p_2026_02 VALUES LESS THAN (TO_DATE('01-03-2026','DD-MM-YYYY')),
  PARTITION p_2026_03 VALUES LESS THAN (TO_DATE('01-04-2026','DD-MM-YYYY')) );

Điểm hay nhất của partition là gì ạ? Là câu lệnh ứng dụng không phải viết lại. Chuyển một bảng thường sang bảng partition thì ứng dụng chạy bình thường, không sửa dòng code nào.

Với viễn thông thì mức chia còn dày hơn. Trong dự án tôi làm, có nơi partition theo giờ, vì dữ liệu sinh ra trong một tiếng đã là vài triệu bản ghi.

Oracle hỗ trợ loại index nào mà SQL Server không có?

Đáng nói nhất là bitmap index. Nó hiệu quả với cột có ít giá trị phân biệt, kiểu giới tính, trạng thái, loại giao dịch. Trong bài toán data warehouse, Oracle kết hợp bitmap index với star transformation cho hiệu quả rất tốt trên các câu lệnh dạng sao.

Index là kỹ thuật tôi dùng đến khoảng 80% các lần tối ưu. Nhưng có index chưa chắc đã nhanh, tôi có phân tích riêng kèm demo trên cả hai bên ở bài Vì sao có Index mà câu SQL vẫn chậm. Thứ tự cột trong index cũng là một cái bẫy, tôi có chia sẻ ở bài Tầm quan trọng của thứ tự các cột trong Index.

PARALLEL chạy được cho câu lệnh nào?

Parallel là chia dữ liệu cho nhiều CPU xử lý cùng lúc rồi gộp kết quả lại. Máy chủ bây giờ đều nhiều core cả, để một luồng chạy lủi thủi thì phí.

Khác biệt nằm ở phạm vi. Oracle hỗ trợ parallel cho cả SELECT, UPDATE, INSERT, DELETE. Trên SQL Server, theo những gì tôi gặp trong dự án, nó chủ yếu phục vụ câu SELECT, còn DML thì cuối cùng vẫn chạy tuần tự.

Anh em có báo cáo chạy cực chậm vào đầu tháng và cuối tháng, bí hết kỹ thuật khác rồi, thì nhớ tới parallel. Nhưng lưu ý: số CPU là có giới hạn. Cái gì cũng parallel thì hết CPU, hệ thống treo là tèo ngay. Dùng cái gì cũng phải điều độ anh em nhá.

Khi hệ thống chậm, ai khoanh vùng nguyên nhân nhanh hơn?

Oracle nhanh hơn, và khoảng cách khá xa. Lý do là báo cáo AWR, viết đầy đủ là Automatic Workload Repository. Nó tự động thu thập theo chu kỳ rồi gói thành một báo cáo cho cả instance. Trong gần như mọi dự án tối ưu tôi làm, AWR là thứ tôi mở đầu tiên.

Trong AWR nên đọc phần nào trước?

Đọc đúng thứ tự bốn phần này thì ra nguyên nhân rất nhanh.

Thứ tựPhần trong AWRNó trả lời câu gì
1DB timeTải của hệ thống khoảng này cao hay thấp. So hai khoảng với nhau thì biết ngay khoảng nào nặng
2Load profile và Instance efficiencyBộ nhớ có ổn không. Chỉ số dưới 95% là tệ, thường phải 99% trở lên mới ngon
3Top Timed Foreground EventsHệ thống đang chờ cái gì. Đây là phần quan trọng nhất
4Top SQL và Segment statisticsCâu lệnh nào và object nào đang ăn tài nguyên

Chỗ số 3 tôi muốn nhấn mạnh, và nhấn mạnh thật. Database chậm thì phải xem ở wait, đừng cắm đầu xem SQL. Cắm đầu vào SQL trước là đi sai đường ngay từ bước một.

Mục Top 5 Timed Foreground Events trong báo cáo AWR, dòng DB CPU chiếm 106,41 phần trăm DB time

Ảnh trên có một chi tiết đáng để ý. Cột % DB time của dòng DB CPU ghi 106,41. Hơn 100% thì vô lý rồi, đúng không ạ. Đó là bug của một số bản cũ, tôi gặp ở nhánh 11.2.0.1. Thấy con số hơn 100% thì đừng hoảng, cũng đừng lấy nó đi kết luận.

Phần Top SQL cho biết mỗi câu chạy bao nhiêu lần, mỗi lần mất bao nhiêu giây, ăn bao nhiêu phần trăm CPU và IO. Phần Segment statistics cho biết trong hàng nghìn bảng và index thì ông nào đọc ghi nhiều nhất. Có lần tôi nhìn ra một index chiếm tới 73% tổng logical reads của cả hệ thống. Thay vì tối ưu mọi thứ, chỉ cần tập trung vào đúng ông đó.

SQL Server có gì tương đương?

Từ bản 2016, SQL Server có Query Store. Nó cho thông tin chi tiết về câu lệnh SQL, và đó là một bước tiến thật. Nhưng nó thiếu bức tranh tổng thể của cả instance như AWR: bộ nhớ, wait event, segment, gói trong một báo cáo. Nên tối ưu trên SQL Server vất vả hơn hẳn. Oracle đắt, nhưng công cụ nó cho tận răng.

Lỡ tay UPDATE quên WHERE thì cứu bằng cách nào?

Trên Oracle thì gõ một câu lệnh là lấy lại được. Trên SQL Server thì phải restore từ bản backup.

Đây là tình huống kinh điển. Anh em định update một bản ghi, sao nhãng thế nào lại quên mất mệnh đề WHERE. Chạy xong còn commit nữa cơ. 10.000 bản ghi đổi hết.

Vì sao Oracle cứu được? Vì dữ liệu trước thay đổi vẫn nằm trong UNDO. Công nghệ để lấy nó ra gọi là Flashback Query, cú pháp là AS OF TIMESTAMP.

Câu lệnh Oracle create table wecommitbackup as select as of timestamp systimestamp trừ 5 phút, kết quả trả về đúng các giá trị cũ A1 A2 A3

Đây là nguyên quy trình xử lý sự cố, chép về dùng luôn:

-- [1] Xem lai du lieu tai thoi diem TRUOC khi lo tay, vi du 5 phut truoc
SELECT *
FROM   wecommitdemo
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '5' MINUTE);

-- [2] Chot ban cu ra mot bang backup
CREATE TABLE wecommitbackup AS
SELECT *
FROM   wecommitdemo
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '5' MINUTE);

-- [3] Doi chieu so ban ghi truoc khi day nguoc du lieu
SELECT COUNT(*) FROM wecommitbackup;

Có bảng backup trong tay rồi thì đẩy lại dữ liệu thế nào là tuỳ anh em. Điều quan trọng là dữ liệu chưa mất.

Một lưu ý thật lòng: cửa sổ thời gian này phụ thuộc vào UNDO còn giữ được bao lâu. Quá hạn thì Flashback Query cũng chịu. Nên phát hiện sự cố sớm phút nào quý phút đó.

Hệ điều hành và bảo mật ảnh hưởng tới lựa chọn ra sao?

Ảnh hưởng nhiều hơn anh em tưởng, và đây là thứ các C level cân nhắc chứ không phải dân kỹ thuật.

Nền tảng chạy được. Trước bản 2017, SQL Server chỉ chạy trên Windows. Oracle hỗ trợ Unix và Linux ngay từ đầu. Trong trải nghiệm của tôi, các nền AIX và Solaris chạy cực trâu bò. Có dự án tôi làm trực tiếp, hệ thống chạy gần 4.000 ngày liên tục không cần reboot.

Định dạng lưu trữ. Oracle có ASM, định dạng riêng của nó. Windows dùng NTFS, Linux dùng ext3 hay ext4, và hệ điều hành đọc được file trên đó. Còn với ASM, hệ điều hành nhìn vào chỉ thấy một cái đĩa, không hiểu gì cả. Nên khi bị ransomware tấn công, tỷ lệ data file bị mã hoá thấp hơn hẳn.

Tính sẵn sàng. Đây là chỗ tôi cho là khác biệt lớn nhất. Oracle RAC cho phép dựng Active Active thật: hai server cùng cài Oracle, cùng đọc, cùng ghi lên bộ data file chung bên dưới, dữ liệu không hỏng. Công nghệ tương đương của hãng khác thường vẫn là Active và Standby, tức một bên đọc ghi, một bên chỉ đọc. SQL Server có Always On Availability Groups từ bản 2012, nhưng bản chất vẫn là đọc ghi và chỉ đọc. Gần như mọi hệ thống core ngân hàng, chứng khoán, viễn thông dùng Oracle thì đều dùng RAC.

Oracle mua lại Sun nên có luôn Solaris và Java. Rất nhiều hệ thống tài chính thời đó chọn nền Java. Hai thứ khớp nhau, thế là lựa chọn càng nghiêng về một phía.

Lịch sử hai hãng lệch nhau bao nhiêu năm?

Lệch khoảng 10 năm ở vạch xuất phát, và khoảng cách đó kéo theo mọi thứ phía sau.

Trục thời gian so sánh các phiên bản Oracle và SQL Server từ năm 1979 tới 2022 kèm mốc ra các tính năng chính
NămOracleSQL Server
1979Bản đầu tiên, đặt tên là V2
1989Oracle 6 đã raBản 1.0, Microsoft hợp tác với Sybase
1995Oracle 7.3Bản 6.0, Microsoft tách ra làm riêng
2000Oracle 9i, có RAC và FlashbackSQL Server 2000
2003Oracle 10g, có AWR
2005SQL Server 2005, có row versioning
2012Oracle 12c, multi-tenantSQL Server 2012, Always On AG
2016SQL Server 2016, Query Store
2017Oracle 18cSQL Server 2017, chạy được Linux

Bản đầu tiên của Oracle mang số 2 chứ không phải 1, vì đặt V1 nghe mất uy tín quá. Chi tiết vui, nhưng nó nói lên cách hãng này nghĩ về thị trường ngay từ đầu.

Theo góc nhìn cá nhân tôi, đi trước cả chục năm đâu phải chỉ là chuyện thời gian. Nhiều khách hàng hơn thì nhiều phản hồi hơn, nhiều bài học hơn, nhiều thứ để cải thiện hơn. Nó cộng dồn.

Chênh lệch tiền license là bao nhiêu?

Oracle đắt khoảng gấp đôi trên cùng một cấu hình server, tính theo giá list mà hai hãng công bố.

Bảng so sánh license Oracle Database Enterprise Edition và Microsoft SQL Server Enterprise Edition trên cùng một server 16 core
KhoảnOracle Database Enterprise EditionMicrosoft SQL Server Enterprise Edition
Cách tínhTheo processorTheo core, bán gói 2 core
Đơn giá47.500 đô một processor13.748 đô một gói 2 core
Số core của server1616
Quy đổi4 processor, giả định 4 core một processor8 gói
Tiền license190.000 đô109.984 đô
Bảo trì năm đầu41.800 đô, tức 22%Không bắt buộc
Tổng năm đầu231.800 đô109.984 đô

Con số 47.500 đô một processor là giá list trong Oracle Technology Price List do chính hãng công bố, kèm phí hỗ trợ 10.450 đô một năm, đúng bằng 22%.

Có một chỗ nhiều anh em hiểu nhầm. Anh em tải Oracle về từ trang của hãng, không phải nhập key nào cả, dùng full tính năng, partition có, nén có, cluster có. Nhưng trong điều khoản có một dòng nhỏ: dùng cho mục đích thương mại mà không trả tiền license thì hãng có quyền kiện. Anh em hết sức lưu ý chỗ này nhá.

Giới hạn thật

Phần này video chưa nói. Tôi bổ sung để anh em đừng mang bảng so sánh trên đi kết luận quá tay.

Bảng giá là giá list, chưa phải giá cuối. Cả hai hãng đều có discount. Con số 231.800 đô cũng chưa phải cuối theo hướng ngược lại: Partitioning và Real Application Clusters là option tính tiền riêng, không nằm trong Enterprise Edition. Theo bảng giá của hãng, Partitioning là 11.500 đô một processor, RAC là 23.000 đô một processor. Dùng thêm thì trả thêm.

Cách quy đổi core sang processor trong demo là con số làm tròn cho dễ hiểu. Oracle quy đổi bằng Core Factor Table, hệ số khác nhau theo dòng chip. Số processor phải mua trên máy thật của anh em có thể khác con số 4 trong bảng.

Leo thang lock của SQL Server tắt được. Microsoft có tuỳ chọn ALTER TABLE ... SET (LOCK_ESCALATION = { AUTO | TABLE | DISABLE }). Với bảng đã partition, đặt AUTO thì khoá chỉ leo tới mức partition chứ không lên cả bảng. Nên đây là mặc định gây đau, không phải bức tường không gỡ được. Chỉ có điều phần lớn hệ thống chạy y nguyên mặc định, và đó mới là vấn đề thật.

Bật row versioning trên SQL Server có giá của nó. Hết chờ, nhưng tempdb gánh thêm version store. Chính tài liệu Microsoft khuyến nghị thử trên môi trường tiền production dưới tải mô phỏng trước khi bật thật.

Video quay tháng 06/2024. Sau đó cả hai hãng đều ra bản mới. Anh em phải kiểm lại trên đúng phiên bản mình đang chạy, đừng lấy nguyên bài này đi cãi nhau.

Trải nghiệm này đến từ hệ thống lớn: core banking, chứng khoán, viễn thông, bảo hiểm. Ở quy mô đó khác biệt lộ ra rất rõ. Hệ thống nhỏ và vừa thì phần lớn khác biệt này anh em sẽ không chạm tới, mà tiền license thì chạm ngay. Chọn theo bài toán, đừng chọn theo bảng tính năng.

Bảy ngày tới anh em làm được gì?

Không cần đổi database. Làm sáu việc này trước đã.

  1. Chạy DBCC USEROPTIONS trên SQL Server production, xem isolation level đang là gì
  2. Kiểm is_read_committed_snapshot_on trong sys.databases, đang tắt thì lên kế hoạch thử trên môi trường test
  3. Xem tempdb đang nằm ở phân vùng nào, có phải phân vùng nhanh nhất không
  4. Bật Extended Events bắt sự kiện lock_escalation, chạy một tuần rồi đếm
  5. Trên Oracle, lấy một báo cáo AWR đúng khung giờ hệ thống chậm, đọc theo thứ tự bốn phần ở trên
  6. Thử Flashback Query trên môi trường test một lần, để lúc có sự cố thật thì tay không run

Câu hỏi hay gặp

Oracle có luôn nhanh hơn SQL Server không?

Không. Bài này nói về hành vi mặc định khi giao dịch đồng thời rất nhiều. Với hệ thống ít tranh chấp, hai bên chạy ngang nhau, và phần lớn chuyện chậm nằm ở câu lệnh với index chứ không nằm ở hãng.

Bật READ_COMMITTED_SNAPSHOT có rủi ro gì không?

Có. tempdb gánh thêm version store, câu ghi tốn thêm chi phí tạo bản cũ. Đổi lại câu đọc không bị chặn. Phải thử dưới tải mô phỏng ở môi trường tiền production, và đảm bảo tempdb nằm trên đĩa nhanh.

SQL Server có gì thay thế được Flashback Query không?

Không có thứ tương đương một lệnh. Hướng thực tế là restore từ backup ra một bản riêng rồi lấy dữ liệu ra. Chậm hơn nhiều, và phải có backup đủ mới.

Ngưỡng leo thang lock của SQL Server là bao nhiêu?

Theo tài liệu Microsoft, là 5.000 khoá trên một lần tham chiếu tới một bảng hoặc một index trong cùng một câu lệnh. Vượt ngưỡng thì engine leo thẳng lên khoá bảng, không leo qua mức trang.

Partition có làm ứng dụng phải sửa code không?

Không. Đây là điểm hay nhất của partition. Chuyển bảng thường sang bảng partition thì câu lệnh viết y như cũ. Cái đổi là chiến lược thực thi bên dưới.

Học tối ưu database nên bắt đầu từ Oracle hay SQL Server?

Bắt đầu từ nguyên lý, đừng bắt đầu từ hãng. Đọc dữ liệu nhất quán, cơ chế khoá, chiến lược thực thi, index. Nắm nguyên lý rồi thì đổi sang MySQL, PostgreSQL hay MongoDB đều bắt nhịp nhanh. Tôi có chia sẻ ở bài MongoDB lúc nhanh lúc chậm và bài Hiệu năng MySQL 8.

Đúc kết

Ba câu thôi.

Một, khác biệt thật giữa Oracle và SQL Server không nằm ở bảng tính năng, nó nằm ở hành vi mặc định khi hệ thống có hàng nghìn giao dịch cùng lúc.

Hai, phần lớn chuyện "hệ thống em hay bị treo" mà tôi gặp đều gỡ được bằng cấu hình, chứ chưa cần đổi database.

Ba, chọn database là chọn theo bài toán và theo túi tiền, không phải chọn theo hãng nào nghe oách hơn.

Anh em cứ mở ba thứ trong bài này ra kiểm trên hệ thống của mình đi: isolation level, vị trí tempdb, và một báo cáo AWR đúng khung giờ chậm. Sai lại sửa. Còn chọn Oracle hay SQL Server thì tuỳ anh em, cân theo đúng bài toán của mình.

Nguồn tham khảo