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!