Vô hiệu hóa các xác nhận rõ ràng trong JDBC, phát hiện chúng trong SQL hoặc đặt cơ sở dữ liệu ở trạng thái chỉ đọc


12

Bối cảnh : Tôi đang làm việc trên http://sqlfiddle.com (trang web của tôi) và đang cố gắng ngăn chặn một con đường lạm dụng có thể xảy ra ở đó. Tôi hy vọng rằng bằng cách hỏi về một vấn đề tôi hiện đang giải quyết, tôi không vô tình làm cho tình trạng lạm dụng tiềm tàng trở nên tồi tệ hơn, nhưng bạn có thể làm gì? Tôi tin tưởng các bạn.

Tôi muốn ngăn bất kỳ người dùng nào thực hiện các cuộc gọi 'cam kết' rõ ràng trong một khối giao dịch nhất định. Từ ngữ cảnh của SQL Fiddle, khối giao dịch là mã được thực thi trên bảng điều khiển bên phải. Về cơ bản, tôi đang lặp đi lặp lại và thực hiện một danh sách các lệnh SQL rõ ràng và tôi muốn đảm bảo rằng tất cả các thay đổi mà chúng thực hiện sẽ được khôi phục vào cuối đợt. Thông thường, những thay đổi của họ sẽ được khôi phục, nhưng đôi khi có một tuyên bố 'cam kết' rõ ràng trong văn bản, và do đó, tất nhiên việc rollback của tôi sẽ không hoạt động. Cam kết rõ ràng này rất có thể từ một người dùng đang cố phá vỡ lược đồ trên SQL Fiddle, vì vậy những người khác làm việc với nó sẽ thấy lỗi.

Kết quả mong muốn chính : Tôi muốn vô hiệu hóa các cam kết rõ ràng ở cấp độ JDBC, nếu có thể. Điều này là do tôi phải hỗ trợ nhiều nhà cung cấp phụ trợ cơ sở dữ liệu và tất nhiên mỗi nhà cung cấp đều có những điểm kỳ quặc ở mức thấp.

Tùy chọn dự phòng : Nếu không thể định cấu hình JDBC để vô hiệu hóa các cam kết rõ ràng, thì tôi sẽ mở các giải pháp để phát hiện các cam kết rõ ràng trong khi xử lý một lô cho mỗi phụ trợ sau: SQL Server, Oracle, MySQL và PostgreQuery.

Đối với SQL Server, tôi đã nghĩ đến giải pháp này: phân tích kế hoạch truy vấn XML cho câu lệnh trước khi tôi thực hiện nó và kiểm tra sự hiện diện của một mục phù hợp với XPath này:

//*[@StatementType="COMMIT TRANSACTION"]

Tôi nghĩ rằng điều này sẽ làm việc khá tốt cho SQL Server. Tuy nhiên, cách tiếp cận này không hoạt động đối với các loại DB khác. Đầu ra kế hoạch thực hiện XML của Oracle cho các cam kết rõ ràng không liên quan đến thực tế rằng bạn đang chạy một câu lệnh cam kết (mà chỉ đơn giản là lặp lại đầu ra của kế hoạch thực hiện từ các truy vấn mà nó cam kết). PostgreSQL và MySQL không cung cấp bất kỳ đầu ra kế hoạch thực hiện nào (XML hoặc cách khác) cho các cam kết rõ ràng.

Điều đó khiến tôi phải kiểm tra tuyên bố thực tế cho từ "cam kết". Điều này sẽ hoạt động, ngoại trừ có thể có tất cả các loại biến thể có thể:

declare @sql varchar(50)
set @sql = 'com' + 'mit'
exec(@sql);

Trên đây là một ví dụ cho SQL Server (mà tôi có thể làm việc xung quanh), nhưng tôi đoán những điều tương tự sẽ có thể xảy ra với Oracle, MySQL và PostgreQuery. Tôi có sai về giả định đó không? Có lẽ họ sẽ không cho phép tuyên bố cam kết "năng động"? Vui lòng sử dụng SQL Fiddle (tốt nhất không phải là lược đồ mẫu hoặc một người khác có khả năng đang làm việc) để xem liệu bạn có thể làm điều gì đó tương tự xảy ra trong Oracle, MySQL và PostgreQuery không. Nếu không, có lẽ phát hiện chuỗi đơn giản có thể làm việc cho những người đó.

Một khả năng khác

Một tùy chọn khác xảy ra với tôi - nếu bạn biết cách đặt bất kỳ cơ sở dữ liệu nào ở chế độ chỉ đọc, thì trong khi ở chế độ đó, không có gì có thể được cam kết, điều đó cũng có thể hoạt động. Tôi sẽ vẫn cần cho phép các giao dịch được bắt đầu và mã chạy trong chúng, miễn là không có gì có thể được cam kết trong khi ở chế độ đó. Điều đó có thể không?

Cập nhật

Những gì tôi đã học gần đây - đây thực sự không phải là vấn đề với PostgreSQL. Rõ ràng các cam kết được ban hành trong một khối giao dịch sẽ không được áp dụng nếu cuối cùng chính khối đó được khôi phục (trong Postgres). Vì vậy, Hoan hô cho Postgres!

Nhờ liên kết của Phil với bài đăng SO, tôi nghĩ rằng tôi có thể sử dụng bản hack DEIBRED INITIALLY DEAXRED cho Oracle để thực hiện những gì tôi đang theo dõi (một lỗi sẽ được đưa ra nếu một cam kết được đưa ra, nhưng tôi có thể khắc phục được điều đó). Điều này sẽ giải quyết Oracle. (Tôi đã nghĩ một lúc rằng các giao dịch lồng nhau có thể hoạt động ở đây, nhưng có vẻ như Oracle không hỗ trợ các giao dịch lồng nhau? Dù sao tôi cũng không thể tìm thấy bất cứ điều gì hoạt động theo cách này).

Chưa thực sự có một giải pháp cho MySQL. Đã thử sử dụng các giao dịch lồng nhau, nhưng điều đó dường như không hoạt động. Tôi nghiêm túc suy nghĩ về các cách tiếp cận quyết liệt hơn đối với MySQL, chẳng hạn như không cho phép bất cứ điều gì ngoài CHỌN ở phía bên phải hoặc thả / tạo lại DB sau mỗi truy vấn. Không có âm thanh tốt mặc dù.

Nghị quyết

Vì vậy, bây giờ tôi đã triển khai các giải pháp được mô tả cho SQL Server và Oracle và như tôi đã đề cập, đây thực sự không phải là vấn đề đối với PostgreQuery. Đối với MySQL, tôi đã thực hiện bước hơi đáng tiếc là hạn chế bảng truy vấn chỉ chọn các câu lệnh. DDL và DML cho MySQL đơn giản sẽ phải được nhập vào bảng lược đồ (phía bên trái). Tôi hy vọng điều này không phá vỡ quá nhiều câu đố cũ, nhưng tôi nghĩ đơn giản đó là những gì phải làm để đảm bảo tính thống nhất của dữ liệu. Cảm ơn!


Đáng nói hơn - tôi cũng đã thực hiện rất nhiều nghiên cứu về các yếu tố kích hoạt "tiền cam kết". Có vẻ như những thứ đó không tồn tại, thật không may, đó cũng không phải là một lựa chọn.
Jake Feasel

2
Đối với Oracle, đây có vẻ là một cách hay để nắm bắt các CAM KẾT: stackoverflow.com/a/6463800/790702 Điều anh ta không đề cập là bạn cũng có thể bắt được vi phạm ràng buộc trong mã của mình, để ngăn chặn tình huống thứ 2 xảy ra
Philᵀᴹ

@Phil vấn đề duy nhất là tôi không có (và không thực sự muốn) kiểm soát định nghĩa của từng bảng (những bảng được xác định trên bảng điều khiển bên trái). Vì vậy, mệnh đề DEAXRALL INITIALLY INITIALLY sẽ không có ở đó (trừ khi có một cách nào đó để tự động làm điều đó cho tất cả các bảng - nói thông qua một trình kích hoạt hệ thống phản hồi để tạo các câu lệnh bảng? Ugh)
Jake Feasel

1
@NickChammas Tôi cần phải vô hiệu hóa các cam kết để tôi có thể giữ lược đồ (như được xác định bởi bảng điều khiển bên trái) ở trạng thái cố định. Có thể có bất kỳ số người nào viết các truy vấn đối với cùng một lược đồ đang cố gắng giải quyết cùng một vấn đề. Để ngăn chúng can thiệp lẫn nhau, tôi cần chắc chắn giữ cho cấu trúc và dữ liệu không bị thay đổi. Điều này được thực hiện thông qua các giao dịch quay vòng, nhưng điều đó không xảy ra nếu mã bên phải được cam kết.
Jake Feasel

2
@RickJames DDL tạo ra các cam kết ngầm trong MySQL và Oracle, nhưng không phải trong PostgreQuery hoặc SQL Server. Các cơ chế tôi đã thực hiện sau bài đăng này xử lý mối quan tâm đó. Cho đến khi nhập SQL tùy ý - đó là toàn bộ vấn đề!
Jake Feasel

Câu trả lời:


3

Đối với Oracle, đây có vẻ là một cách tốt để bắt các CAM KẾT:

/programming//a/6463800/790702

Điều anh ấy không đề cập là bạn cũng có thể bắt được vi phạm ràng buộc trong mã của mình, để ngăn chặn tình huống thứ 2 xảy ra.


Tuyệt, cảm ơn lần nữa Phil. Tôi đã có thể sử dụng tốt kỹ thuật này cho Oracle. Nó làm cho tôi muốn các cơ sở dữ liệu khác được hỗ trợ các ràng buộc hoãn lại.
Jake Feasel

Đừng lo lắng. Thả vào trò chuyện và nói xin chào :)
Philᵀᴹ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.