Tối ưu SQL (phần 7): Chuyện ngắn của ID

Tối ưu hiệu năng SQL (phần 1): DATETIME

Tối ưu hiệu năng SQL (phần 2): DELETE

Tối ưu hiệu năng SQL (phần 3): Exists, IN và người thứ ba

Tối ưu hiệu năng SQL (phần 4): Trigger

Tối ưu hiệu năng SQL phần 5: RANDOM

Tối ưu hiệu năng SQL (phần 6): Update hay Merge?

Tình hình là hôm qua, trong những ngày cuối cùng làm việc ở công ty cũ thì mình có gặp 1 câu chuyện nho nhỏ về việc sử dụng ID trong SQL Server. Đây có lẽ là 1 bài học khá hay cho việc không hiểu hết ý nghĩa các thành phần ở SQL Server cũng như là bài học về sự thay đổi liên tục trong phần mềm. Câu chuyện được bắt đầu như sau

core-story

Vào năm Phật lịch 2561 tức năm 2017 đối với Jesus, trong 1 buổi sáng ở xứ sở Đông Lào xa xăm nằm ở bên kia Đại Dương so với đất nước Huê Kì hùng mạnh có 1 chàng trai trẻ cặm cùi hì hục ngồi tu luyện một môn võ công mà hầu như trong đám Đép Sinh ai cũng từng kinh qua vài lân đó chính là SQL thần chưởng.

ceeyg0dwaaim5nb

Cách đây đôi ba năm trong 1 lần thi triển tuyệt kĩ trên đỉnh Hoa Sơn cùng với Thiên hạ ngũ tuyệt, chàng ta có sử dụng đến @@IDENTITY nhằm lấy ra những thông tin từ Tăng Trường Tự (hay trường tự tăng =)) ) nằm trong trang 2316 dòng thứ 415 của cuốn Kinh SQL Cự Đà phổ quyển thứ nhất.  Khẩu quyết của môn tuyệt học này được chàng trai sử dụng đó là:

TABLE có 4 cột A, B,C,D với cột A được set là indentity với seed 1 và start từ 1

INSERT INTO TABLE (B, C, D) VALUES (1, 2,3)

RETURN @@IDENTITY

Chỉ với vài dòng khẩu quyết ngắn ngủi, chàng trai đã luyện được môn võ học thượng thừa gây chấn động giới võ lâm; giúp cho bá tánh khắp nơi trong bầu trời xứ Đông Lào yên vui thái bình.

thienha02

Rồi bỗng 1 ngày trên trời xuất hiện một đám mây đen vây quanh Phân đà mà chàng trai đang ở. Biết có chuyện chẳng lành nhưng chàng trai đã không thể ngờ được rằng đây chính là 1 điều báo sẽ có 1 chuyện khủng khiếp sắp đến với chàng.

bw_storm_clouds_texture

Và quả nhiên đúng như vậy. Chi 2 hôm sau thì đùng 1 phát trường @@IDENTITY không còn trả đúng kết quả khi thực hiện câu INSERT nữa. Chàng loay hoay tìm cách giải quyết nhưng đều bó tay, chàng nghĩ mãi không ra, môn võ học này có điểm gì sai ở đâu mà sao chàng không thể luyện lên được tầng cao nhất đây !!! Chính từ đó đã gây ra đại loại trong giới giang hồ, đâu đâu cũng nghe thấy, nhìn thấy sai sót của chàng; khắp nơi dân chúng trong thiên hạ kêu gào gầm rú muốn xử tử chàng; muốn đem chàng ra xử trảm ngay.

1-44

Bất lực, chàng trai chỉ biết lặng lẽ lui về ở ẩn để lại sự lầm than, oán trách của bao người; mỗi khi có ai nhờ vả thì chàng cũng giúp họ vượt qua lỗi lầm do chính chàng gây ra rồi lại thôi. Tuy vậy trong lòng chàng không một ngày nào là không nghĩ đến lý do vì sao chàng có thể gây ra 1 tội ác to lớn như vậy mà không hề hiểu?

Chàng quyết tâm tu chí lên Sờ tắc O vờ Fờ lâu Kinh Các (StackOverFlow) để nghiên cứu cách giải thoát cho chúng sinh khỏi con đường khổ ái hiện tại. Trong các cuốn Kinh mà chàng đọc được có đoạn

@@IDENTITY returns the last identity value generated for any table in the current session, across all scopes. You need to be careful here, since it’s across scopes. You could get a value from a trigger, instead of your current statement.

Đọc đến đây chàng mới như ngớ người ra vì năm đó chàng có giới thiệu với anh em đồng đạo võ lâm 1 lần về một môn tuyệt học võ học mà chàng đã tu luyện được trong

Tối ưu hiệu năng SQL (phần 4): Trigger

Chia sẻ sourcecode chuyển đổi CSDL

Vậy là sai lầm của chàng là do chàng để luyện võ công của mình cùng với việc học thêm Trigger thần quyền. 2 môn võ này đã đánh nhau khiến chàng tẩu hỏa nhập ma mà không biết, chàng đọc tiếp thì có câu

SCOPE_IDENTITY() returns the last identity value generated for any table in the current session and the current scope. Generally what you want to use.

Chàng liền lập tức sử dụng SCOPE_IDENTITY() và kết quả mang lại đã đúng ngay lập tức :3 Chàng vui sướng không để đâu cho hết, chàng không ngại gian khổ liền lập tức rời ngay khỏi Tàng Kinh Các và mang cuốn Kì thư về cho bá tánh.

Hiện tại thì bá tánh đã được giải thoát khỏi sai lầm do chàng gây ra còn tương lai thế nào thì chàng cũng chưa rõ vì chàng tiếp tục ngâm cứu cuốn Kì thư cầm về. Khi mở lại chàng lại phát hiện ra môn võ công mình vừa luyện được cũng chưa chắc có thể giải thoát toàn bộ chúng sinh khỏi khổ ải (https://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/). Chàng lại đi luyện mất rồi, câu chuyện đành kết thúc ở đây,; khi nào chàng hạ sơn thì tại hạ sẽ viết tiếp cho mọi người biết đến :3

Dịch lại

Đại ý câu chuyện của mình là đợt trước mình có triển khai 1 con hệ thống có sử dụng cái trường tự tăng trong bảng dữ liệu. Ở trong đó thì mính có dùng store với thằng @@IDENTITY để lấy ra cái ID sau khi insert vào bảng dữ liệu đó thì thấy vẫn ổn. Vậy là tưởng ngon lành rồi ai dè đợt vừa rồi có làm cái chuyển CSDL từ SQL sang Oracle. Mình có thêm vào bảng đó cũng như các bảng khác trong SQL 1 đống trigger ấy mà, vậy là từ đó lỗi chồng lỗi ở chỗ @@IDENTITY kia, nó trả về kết quả được chạy ra từ câu insert trigger xa xăm nào đó mà có giời mới biết dẫn đến hệ thống của mình lúc lỗi lúc không mà mình không đoán ra được vì sao :(( Ai dè đến sáng hôm qua thì mình hên xui thế nào lại tìm ra được lý do mới hay. Thật không ngờ lý do chính là không nên sử dụng @@IDENTIY mà hãy sử dụng SCOPE_IDENTITY; thế là mình lập tức thay thử vào và đã khắc phục được cái lỗi khù khoằm kia. Nhưng theo như đọc thì tốt nhất là nên sử dụng cái OUTPUT là chuẩn hơn. Phần này mình đang đọc tiếp có gì sẽ viết để chia sẻ lại cho anh em sau :3

Từ câu chuyện của mình đã dính phải; mong anh em lưu ý khi áp dụng 1 thay đổi gì nên hệ thống mà không được kiểm thử kĩ càng thì đừng vội vàng mang đi triển khai cũng như việc dùng mà không hiểu bản chất ngay từ đầu như mình :)) Something just like this :3

Tham khảo

http://stackoverflow.com/questions/42648/best-way-to-get-identity-of-inserted-row

https://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution/

Advertisements

4 thoughts on “Tối ưu SQL (phần 7): Chuyện ngắn của ID

  1. Pingback: Tối ưu SQL (phần 10): Lại là câu chuyện về GUID ID | Code, code and more code

  2. Pingback: Tối ưu SQL (phần 9): tính tổng các dòng | Code, code and more code

  3. Pingback: Tối ưu SQL phần 8: 1 câu chuyện đơn gian về việc cộng chuỗi | Code, code and more code

  4. Pingback: Tối ưu hiệu năng SQL (phần 6): Update hay Merge? | Code, code and more code

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s