InterSystems IRIS DBMS hỗ trợ các cấu trúc thú vị để lưu trữ dữ liệu - toàn cục. Về cơ bản, đây là các khóa đa cấp với nhiều tính năng bổ sung khác nhau dưới dạng giao dịch, chức năng duyệt nhanh cây dữ liệu, khóa và ngôn ngữ ObjectScript của riêng nó.
Đọc thêm về Globals trong chuỗi bài viết “Globals là thanh kiếm kho báu để lưu trữ dữ liệu”:
Tôi bắt đầu quan tâm đến cách các giao dịch được thực hiện trên toàn cầu, có những tính năng gì. Xét cho cùng, đây là một cấu trúc lưu trữ dữ liệu hoàn toàn khác so với các bảng thông thường. Mức độ thấp hơn nhiều.
Như đã biết từ lý thuyết cơ sở dữ liệu quan hệ, việc thực hiện tốt các giao dịch phải đáp ứng được yêu cầu :
A – Atomic (tính nguyên tử). Tất cả những thay đổi được thực hiện trong giao dịch hoặc không có thay đổi nào đều được ghi lại.
C - Tính nhất quán. Sau khi giao dịch hoàn tất, trạng thái logic của cơ sở dữ liệu phải nhất quán bên trong. Theo nhiều cách, yêu cầu này liên quan đến người lập trình, nhưng trong trường hợp cơ sở dữ liệu SQL, nó cũng liên quan đến các khóa ngoại.
Tôi - Cô lập. Các giao dịch chạy song song sẽ không ảnh hưởng lẫn nhau.
D – Bền bỉ. Sau khi hoàn thành giao dịch thành công, các sự cố ở mức độ thấp hơn (chẳng hạn như mất điện) sẽ không ảnh hưởng đến dữ liệu do giao dịch thay đổi.
Toàn cầu là cấu trúc dữ liệu phi quan hệ. Chúng được thiết kế để chạy siêu nhanh trên phần cứng rất hạn chế. Hãy xem xét việc thực hiện các giao dịch trên toàn cầu bằng cách sử dụng .
Để hỗ trợ các giao dịch trong IRIS, các lệnh sau được sử dụng: , , .
1. Tính nguyên tử
Cách dễ nhất để kiểm tra là tính nguyên tử. Chúng tôi kiểm tra từ bảng điều khiển cơ sở dữ liệu.
Kill ^a
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TCOMMITSau đó chúng tôi kết luận:
Write ^a(1), “ ”, ^a(2), “ ”, ^a(3)Chúng tôi nhận được:
1 2 3Mọi thứ đều ổn. Tính nguyên tử được duy trì: tất cả các thay đổi đều được ghi lại.
Hãy làm phức tạp nhiệm vụ, đưa ra lỗi và xem giao dịch được lưu như thế nào, một phần hay không.
Hãy kiểm tra lại tính nguyên tử:
Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3Sau đó chúng ta sẽ cưỡng bức dừng container, khởi chạy nó và xem.
docker kill my-irisLệnh này gần như tương đương với việc buộc tắt máy, vì nó gửi tín hiệu SIGKILL để dừng quá trình ngay lập tức.
Có lẽ giao dịch đã được lưu một phần?
WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)- Không, nó không sống sót được.
Hãy thử lệnh rollback:
Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TROLLBACK
WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)Không có gì còn sót lại.
2. Tính nhất quán
Vì trong cơ sở dữ liệu dựa trên toàn cầu, các khóa cũng được tạo trên toàn cục (để tôi nhắc bạn rằng toàn cục là cấu trúc cấp thấp hơn để lưu trữ dữ liệu so với bảng quan hệ), để đáp ứng yêu cầu nhất quán, phải bao gồm một thay đổi về khóa trong cùng một giao dịch với sự thay đổi trên toàn cầu.
Ví dụ: chúng tôi có ^person toàn cầu, trong đó chúng tôi lưu trữ các tính cách và sử dụng TIN làm khóa.
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
...Để tìm kiếm nhanh theo họ và tên, chúng tôi đã tạo khóa ^index.
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1Để cơ sở dữ liệu nhất quán, chúng ta phải thêm cá nhân như thế này:
TSTART
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
TCOMMITTheo đó, khi xóa chúng ta cũng phải sử dụng một giao dịch:
TSTART
Kill ^person(1234567)
ZKill ^index(‘Kamenev’, ‘Sergey’, 1234567)
TCOMMITNói cách khác, việc đáp ứng yêu cầu về tính nhất quán hoàn toàn phụ thuộc vào vai của lập trình viên. Nhưng khi nói đến toàn cầu, điều này là bình thường do tính chất cấp thấp của chúng.
3. Cách ly
Đây là nơi mà sự hoang dã bắt đầu. Nhiều người dùng đồng thời làm việc trên cùng một cơ sở dữ liệu, thay đổi cùng một dữ liệu.
Tình huống này có thể so sánh với việc nhiều người dùng đồng thời làm việc với cùng một kho lưu trữ mã và cố gắng thực hiện đồng thời các thay đổi đối với nhiều tệp cùng một lúc.
Cơ sở dữ liệu sẽ sắp xếp tất cả theo thời gian thực. Xem xét rằng ở các công ty nghiêm túc thậm chí còn có một người đặc biệt chịu trách nhiệm kiểm soát phiên bản (để hợp nhất các chi nhánh, giải quyết xung đột, v.v.) và cơ sở dữ liệu phải thực hiện tất cả những điều này trong thời gian thực, độ phức tạp của nhiệm vụ và tính chính xác của thiết kế cơ sở dữ liệu và mã phục vụ nó.
Cơ sở dữ liệu không thể hiểu ý nghĩa của các hành động do người dùng thực hiện để tránh xung đột nếu họ đang làm việc trên cùng một dữ liệu. Nó chỉ có thể hoàn tác một giao dịch xung đột với giao dịch khác hoặc thực hiện chúng một cách tuần tự.
Một vấn đề khác là trong quá trình thực hiện một giao dịch (trước khi thực hiện một cam kết), trạng thái của cơ sở dữ liệu có thể không nhất quán, do đó, mong muốn các giao dịch khác không có quyền truy cập vào trạng thái không nhất quán của cơ sở dữ liệu, điều này đạt được trong cơ sở dữ liệu quan hệ. theo nhiều cách: tạo ảnh chụp nhanh, hàng nhiều phiên bản, v.v.
Khi thực hiện các giao dịch song song, điều quan trọng đối với chúng tôi là chúng không gây trở ngại cho nhau. Đây là tính chất của sự cô lập.
SQL định nghĩa 4 mức cô lập:
- ĐỌC KHÔNG CAM KẾT
- ĐỌC CAM KẾT
- ĐỌC LẶP LẠI
- Có thể tuần tự hóa
Chúng ta hãy xem xét từng cấp độ riêng biệt. Chi phí thực hiện mỗi cấp độ tăng theo cấp số nhân.
ĐỌC KHÔNG CAM KẾT - đây là mức độ cô lập thấp nhất nhưng đồng thời cũng nhanh nhất. Các giao dịch có thể đọc được những thay đổi do nhau thực hiện.
ĐỌC CAM KẾT là mức độ cô lập tiếp theo, đó là một sự thỏa hiệp. Các giao dịch không thể đọc các thay đổi của nhau trước khi chuyển giao, nhưng chúng có thể đọc bất kỳ thay đổi nào được thực hiện sau khi chuyển giao.
Nếu chúng ta có một giao dịch T1 dài, trong đó các cam kết diễn ra trong các giao dịch T2, T3 ... Tn, hoạt động với cùng dữ liệu với T1, thì khi yêu cầu dữ liệu trong T1, chúng ta sẽ nhận được một kết quả khác nhau mỗi lần. Hiện tượng này được gọi là việc đọc không thể lặp lại.
ĐỌC LẶP LẠI — ở mức cô lập này, chúng ta không có hiện tượng đọc không lặp lại, do thực tế là với mỗi yêu cầu đọc dữ liệu, một ảnh chụp nhanh của dữ liệu kết quả được tạo ra và khi được sử dụng lại trong cùng một giao dịch, dữ liệu từ ảnh chụp nhanh đó Được sử dụng. Tuy nhiên, có thể đọc dữ liệu ảo ở mức độ cô lập này. Điều này đề cập đến việc đọc các hàng mới được thêm vào bởi các giao dịch được cam kết song song.
Có thể tuần tự hóa - mức cách điện cao nhất. Nó được đặc trưng bởi thực tế là dữ liệu được sử dụng theo bất kỳ cách nào trong giao dịch (đọc hoặc thay đổi) chỉ có sẵn cho các giao dịch khác sau khi hoàn thành giao dịch đầu tiên.
Trước tiên, hãy tìm hiểu xem liệu có sự tách biệt giữa các hoạt động trong một giao dịch với luồng chính hay không. Hãy mở 2 cửa sổ terminal.
Kill ^t
Write ^t(1)
2
TSTART
Set ^t(1)=2Không có sự cô lập. Một chủ đề xem chủ đề thứ hai đã mở giao dịch đang làm gì.
Hãy xem liệu các giao dịch của các luồng khác nhau có thấy điều gì đang xảy ra bên trong chúng hay không.
Hãy mở 2 cửa sổ terminal và mở song song 2 giao dịch.
kill ^t
TSTART
Write ^t(1)
3
TSTART
Set ^t(1)=3
Các giao dịch song song nhìn thấy dữ liệu của nhau. Vì vậy, chúng tôi đã có mức cách ly đơn giản nhất nhưng cũng nhanh nhất, READ UNCOMMITED.
Về nguyên tắc, điều này có thể được mong đợi đối với các công ty toàn cầu, nơi hiệu suất luôn được ưu tiên hàng đầu.
Điều gì sẽ xảy ra nếu chúng ta cần mức độ cô lập cao hơn trong hoạt động trên toàn cầu?
Ở đây bạn cần suy nghĩ xem tại sao lại cần đến mức cách ly và cách chúng hoạt động.
Mức cô lập cao nhất, SERIALIZE, có nghĩa là kết quả của các giao dịch được thực hiện song song tương đương với việc thực hiện tuần tự của chúng, đảm bảo không có xung đột.
Chúng ta có thể thực hiện việc này bằng cách sử dụng khóa thông minh trong ObjectScript, có nhiều cách sử dụng khác nhau: bạn có thể thực hiện khóa thông thường, tăng dần, nhiều khóa bằng lệnh .
Mức cô lập thấp hơn là sự đánh đổi được thiết kế để tăng tốc độ cơ sở dữ liệu.
Hãy xem cách chúng ta có thể đạt được các mức độ cách ly khác nhau bằng cách sử dụng khóa.
Toán tử này cho phép bạn không chỉ sử dụng các khóa độc quyền cần thiết để thay đổi dữ liệu mà còn cho phép sử dụng các khóa chia sẻ, có thể thực hiện song song một số luồng khi chúng cần đọc dữ liệu mà các quy trình khác không nên thay đổi trong quá trình đọc.
Thông tin thêm về phương pháp chặn hai pha bằng tiếng Nga và tiếng Anh:
→
→
Khó khăn là trong quá trình giao dịch, trạng thái của cơ sở dữ liệu có thể không nhất quán, nhưng dữ liệu không nhất quán này lại được hiển thị cho các quy trình khác. Làm thế nào để tránh điều này?
Bằng cách sử dụng khóa, chúng ta sẽ tạo các cửa sổ hiển thị trong đó trạng thái của cơ sở dữ liệu sẽ nhất quán. Và tất cả quyền truy cập vào các cửa sổ hiển thị trạng thái đã thỏa thuận như vậy sẽ được kiểm soát bằng các khóa.
Các khóa chia sẻ trên cùng một dữ liệu có thể được sử dụng lại—một số quy trình có thể sử dụng chúng. Các khóa này ngăn các quá trình khác thay đổi dữ liệu, tức là. chúng được sử dụng để tạo thành các cửa sổ có trạng thái cơ sở dữ liệu nhất quán.
Khóa độc quyền được sử dụng để thay đổi dữ liệu - chỉ một quy trình có thể sử dụng khóa như vậy. Một khóa độc quyền có thể được thực hiện bởi:
- Bất kỳ quy trình nào nếu dữ liệu miễn phí
- Chỉ quy trình có khóa chung đối với dữ liệu này và là quy trình đầu tiên yêu cầu khóa độc quyền.

Cửa sổ hiển thị càng hẹp thì các quy trình khác phải chờ nó càng lâu, nhưng trạng thái của cơ sở dữ liệu bên trong nó càng nhất quán.
READ_COMMITTED — bản chất của cấp độ này là chúng tôi chỉ thấy dữ liệu đã cam kết từ các luồng khác. Nếu dữ liệu trong một giao dịch khác chưa được cam kết thì chúng ta sẽ thấy phiên bản cũ của nó.
Điều này cho phép chúng ta thực hiện song song công việc thay vì chờ khóa được giải phóng.
Nếu không có các thủ thuật đặc biệt, chúng ta sẽ không thể xem phiên bản cũ của dữ liệu trong IRIS, vì vậy chúng ta sẽ phải thực hiện bằng cách khóa.
Theo đó, chúng tôi sẽ phải sử dụng các khóa chia sẻ để cho phép dữ liệu chỉ được đọc tại những thời điểm nhất quán.
Giả sử chúng ta có một cơ sở người dùng ^người chuyển tiền cho nhau.
Thời điểm chuyển từ người 123 sang người 242:
LOCK +^person(123), +^person(242)
Set ^person(123, amount) = ^person(123, amount) - amount
Set ^person(242, amount) = ^person(242, amount) + amount
LOCK -^person(123), -^person(242)Thời điểm yêu cầu số tiền từ người 123 trước khi ghi nợ phải kèm theo một khối độc quyền (mặc định):
LOCK +^person(123)
Write ^person(123)Và nếu bạn cần hiển thị trạng thái tài khoản trong tài khoản cá nhân của mình thì bạn có thể sử dụng khóa chung hoặc hoàn toàn không sử dụng:
LOCK +^person(123)#”S”
Write ^person(123)Tuy nhiên, nếu chúng ta giả định rằng các hoạt động cơ sở dữ liệu được thực hiện gần như ngay lập tức (để tôi nhắc bạn rằng toàn cầu là một cấu trúc cấp thấp hơn nhiều so với bảng quan hệ), thì nhu cầu về cấp độ này sẽ giảm.
ĐỌC LẶP LẠI - Mức cô lập này cho phép đọc nhiều dữ liệu có thể được sửa đổi bởi các giao dịch đồng thời.
Theo đó, chúng tôi sẽ phải đặt khóa chung để đọc dữ liệu mà chúng tôi thay đổi và khóa riêng cho dữ liệu mà chúng tôi thay đổi.
May mắn thay, toán tử LOCK cho phép bạn liệt kê chi tiết tất cả các khóa cần thiết, trong đó có thể có rất nhiều khóa, trong một câu lệnh.
LOCK +^person(123, amount)#”S”
чтение ^person(123, amount)các hoạt động khác (tại thời điểm này, các luồng song song cố gắng thay đổi ^người(123, số tiền), nhưng không thể)
LOCK +^person(123, amount)
изменение ^person(123, amount)
LOCK -^person(123, amount)
чтение ^person(123, amount)
LOCK -^person(123, amount)#”S”Khi liệt kê các khóa được phân tách bằng dấu phẩy, chúng sẽ được lấy tuần tự, nhưng nếu bạn làm như vậy:
LOCK +(^person(123),^person(242))sau đó chúng được lấy một cách nguyên tử cùng một lúc.
XÁC NHẬN — chúng ta sẽ phải đặt khóa để cuối cùng tất cả các giao dịch có dữ liệu chung được thực hiện tuần tự. Đối với phương pháp này, hầu hết các khóa phải độc quyền và được sử dụng ở những khu vực nhỏ nhất trên toàn cầu để đạt hiệu suất.
Nếu chúng ta nói về việc ghi nợ tiền trong ^người toàn cầu, thì chỉ có mức cô lập SERIALIZE mới được chấp nhận đối với nó, vì tiền phải được chi tiêu theo tuần tự nghiêm ngặt, nếu không thì có thể chi cùng một số tiền nhiều lần.
4. Độ bền
Tôi đã tiến hành thử nghiệm với việc cắt cứng hộp đựng bằng cách sử dụng
docker kill my-irisCăn cứ đã chịu đựng tốt chúng. Không có vấn đề nào được xác định.
Kết luận
Đối với toàn cầu, InterSystems IRIS có hỗ trợ giao dịch. Chúng thực sự nguyên tử và đáng tin cậy. Để đảm bảo tính nhất quán của cơ sở dữ liệu dựa trên toàn cầu, cần có nỗ lực của người lập trình và sử dụng các giao dịch vì nó không có các cấu trúc tích hợp phức tạp như khóa ngoại.
Mức cô lập của toàn cầu không sử dụng khóa là READ UNCOMMITED và khi sử dụng khóa, nó có thể được đảm bảo lên đến mức SERIALIZE.
Độ chính xác và tốc độ của các giao dịch trên toàn cầu phụ thuộc rất nhiều vào kỹ năng của người lập trình: các khóa được chia sẻ càng rộng rãi khi đọc thì mức độ cách ly càng cao và các khóa độc quyền được thực hiện càng hẹp thì hiệu suất càng nhanh.
Nguồn: www.habr.com
