Trình tự không tạo các bộ số khoảng trống, và thực sự không có cách nào khiến chúng làm điều đó vì một cuộn ngược hoặc lỗi sẽ "sử dụng" số thứ tự.
Tôi đã viết một bài viết về điều này một thời gian trước đây. Nó hướng đến Oracle nhưng thực sự là về các nguyên tắc cơ bản của các số khoảng trống, và tôi nghĩ điều tương tự cũng áp dụng ở đây.
Vâng, điều đó lại xảy ra. Ai đó có asked cách thực hiện một yêu cầu để tạo ra một chuỗi số không có khoảng trống và một số người nói trên đã nói lên (và ở đây tôi diễn giải một chút) rằng điều này sẽ giết hiệu năng hệ thống, điều đó hiếm khi là yêu cầu hợp lệ , bất cứ ai viết yêu cầu là một kẻ ngốc blah blah blah.
Khi tôi chỉ ra chủ đề, đôi khi đó là yêu cầu pháp lý chính hãng để tạo chuỗi số liệu không có khoảng trống. Số hóa đơn cho hơn 2.000.000 tổ chức ở Vương quốc Anh là VAT (thuế bán hàng) đã đăng ký có yêu cầu như vậy và lý do cho điều này khá rõ ràng: khiến việc ẩn doanh thu từ cơ quan thuế trở nên khó khăn hơn. Tôi đã thấy nhận xét rằng đó là một yêu cầu ở Tây Ban Nha và Bồ Đào Nha, và tôi sẽ không ngạc nhiên nếu nó không phải là một yêu cầu ở nhiều quốc gia khác.
Vì vậy, nếu chúng tôi chấp nhận rằng đó là yêu cầu hợp lệ, trong trường hợp nào là chuỗi số liệu không có khoảng trống * về số có vấn đề? Nhóm suy nghĩ thường xuyên sẽ có bạn tin rằng nó luôn luôn là, nhưng trên thực tế nó chỉ là một vấn đề tiềm năng trong những trường hợp rất cụ thể.
- Các dãy số phải không có khoảng trống.
- Nhiều quy trình tạo các thực thể mà số được liên kết (ví dụ: hóa đơn).
- Các số phải được tạo tại thời điểm thực thể được tạo.
Nếu tất cả các yêu cầu này phải được đáp ứng sau đó bạn có một điểm của serialization trong ứng dụng của bạn, và chúng tôi sẽ thảo luận rằng trong một khoảnh khắc.
Trước tiên, hãy nói về các phương pháp triển khai yêu cầu loạt số nếu bạn có thể xóa bất kỳ yêu cầu nào trong số đó.
Nếu chuỗi số của bạn có thể có khoảng trống (và bạn có nhiều quy trình yêu cầu tạo số ngay lập tức) thì hãy sử dụng đối tượng Oracle Sequence. Chúng có hiệu suất rất cao và các tình huống trong đó khoảng trống có thể được mong đợi đã được thảo luận rất tốt. Nó không phải là quá khó khăn để giảm thiểu số lượng bỏ qua bằng cách làm cho các nỗ lực thiết kế để giảm thiểu cơ hội của một thất bại quá trình giữa thế hệ của số và cam kết giao dịch, nếu đó là quan trọng.
Nếu bạn không có nhiều quy trình tạo các thực thể (và bạn cần một chuỗi số không có khoảng trống phải được tạo ngay), như trường hợp tạo hóa đơn hàng loạt, thì bạn đã có điểm của serialization. Điều đó có thể không phải là một vấn đề, và có thể là một cách hiệu quả để thực hiện thao tác cần thiết. Việc tạo ra các số khoảng trống là khá nhỏ trong trường hợp này. Bạn có thể đọc giá trị tối đa hiện tại và áp dụng giá trị gia tăng cho mỗi thực thể với một số kỹ thuật. Ví dụ, nếu bạn đang chèn một lô mới hoá đơn vào bảng hóa đơn của bạn từ một bàn làm việc tạm thời bạn có thể:
insert into
invoices
(
invoice#,
...)
with curr as (
select Coalesce(Max(invoice#)) max_invoice#
from invoices)
select
curr.max_invoice#+rownum,
...
from
tmp_invoice
...
Tất nhiên bạn sẽ bảo vệ quá trình của bạn để chỉ một trường hợp có thể chạy cùng một lúc (có thể với DBMS_Lock nếu bạn đang sử dụng Oracle) và bảo vệ hóa đơn # bằng khóa duy nhất, và có thể kiểm tra các giá trị bị thiếu bằng mã riêng nếu bạn thực sự quan tâm.
Nếu bạn không cần tạo các số ngay lập tức (nhưng bạn cần chúng không có khoảng trống và nhiều quy trình tạo ra các thực thể) thì bạn có thể cho phép các thực thể được tạo và giao dịch được cam kết, và sau đó để lại số cho một công việc hàng loạt đơn lẻ. Bản cập nhật trên bảng thực thể hoặc chèn vào bảng riêng biệt.
Vì vậy, nếu chúng ta cần trifecta của thế hệ tức thời của một chuỗi các số không có khoảng trống bởi nhiều quy trình? Tất cả những gì chúng ta có thể làm là cố gắng giảm thiểu thời gian serialization trong quá trình, và tôi đưa ra lời khuyên sau đây, và chào đón bất kỳ lời khuyên bổ sung nào (hoặc tư vấn phản đối).
- cửa hàng giá trị hiện tại của bạn trong một bảng chuyên dụng. KHÔNG sử dụng một chuỗi.
- Đảm bảo rằng tất cả các quy trình đều sử dụng cùng một mã để tạo số mới bằng cách đóng gói nó trong một hàm hoặc thủ tục.
- Truy cập hàng loạt vào trình tạo số với DBMS_Lock, đảm bảo rằng mỗi chuỗi có khóa chuyên dụng riêng.
- Giữ khóa trong bộ tạo chuỗi cho đến khi giao dịch tạo thực thể của bạn hoàn tất bằng cách nhả khóa trên cam kết
- Làm chậm quá trình tạo số cho đến giây phút cuối cùng có thể.
- Hãy xem xét tác động của một lỗi không mong muốn sau khi tạo số và trước khi cam kết hoàn thành - ứng dụng sẽ cuộn lại một cách duyên dáng và nhả khóa hay nó sẽ giữ khóa trên trình tạo chuỗi cho đến khi phiên ngắt kết nối sau? Bất kể phương thức nào được sử dụng, nếu giao dịch thất bại thì số sê-ri phải được "trả về hồ bơi".
- Bạn có thể gói gọn toàn bộ thứ trong một trình kích hoạt trên bàn của thực thể không? Bạn có thể gói gọn nó trong một bảng hoặc cuộc gọi API khác chèn hàng và cam kết chèn tự động không?
Original article
Nguồn
2013-09-25 13:29:28
Có nhiều giải pháp phức tạp cho một chuỗi Gapless. Nhưng nếu bạn muốn nó đơn giản và chính xác, hãy thực hiện nó trong khối 'try', kiểm tra một ngoại lệ vi phạm chính và thử lại. [Câu trả lời của tôi ở đây] (http://stackoverflow.com/a/16465158/131874). –
Xem thêm http://stackoverflow.com/questions/9984196/rails-postgres-does-not-re-use-deleted-ids-but-mysql-does/ – IMSoP
Bản sao có thể có của [Khoảng trống giữa id khóa chính trong bảng sql ] (http://stackoverflow.com/questions/39099905/gaps-between-primary-key-id-in-sql-table) – e4c5