Latin-1 có nên được sử dụng trên UTF-8 khi nói đến cấu hình cơ sở dữ liệu không?


65

Chúng tôi đang sử dụng MySQL tại công ty tôi làm việc và chúng tôi xây dựng cả ứng dụng nội bộ và ứng dụng khách sử dụng Ruby on Rails.

Khi tôi bắt đầu làm việc ở đây, tôi gặp phải một vấn đề mà tôi chưa bao giờ gặp phải trước đây; cơ sở dữ liệu trên máy chủ sản xuất được đặt thành Latin-1, nghĩa là viên ngọc MySQL ném ngoại lệ bất cứ khi nào có đầu vào của người dùng nơi người dùng sao chép và dán các ký tự UTF-8.

Sếp của tôi gọi những "nhân vật xấu" này vì hầu hết trong số họ là những nhân vật không thể in được và nói rằng chúng tôi cần loại bỏ chúng. Tôi đã tìm thấy một vài cách để làm điều này, nhưng cuối cùng chúng tôi đã kết thúc trong một tình huống cần có một nhân vật UTF-8. Thêm vào đó là một chút rắc rối, đặc biệt vì có vẻ như giải pháp duy nhất tôi từng đọc về vấn đề này là chỉ đặt cơ sở dữ liệu thành UTF-8 (có ý nghĩa với tôi).

Đối số duy nhất mà tôi đã nghe thấy khi gắn bó với Latin-1 là cho phép các ký tự UTF-8 không in được có thể làm rối các tìm kiếm văn bản / toàn văn bản trong MySQL. Điều này có thực sự đúng không?

Có những lý do khác người ta nên sử dụng Latin-1 trên UTF-8? Theo hiểu biết của tôi thì nó vượt trội và trở nên phổ biến hơn.


4
@jon LATIN-1 không phải là tiếng Anh cụ thể. Tiếng Tây Ban Nha được chứa hoàn hảo ở đó, cũng như tiếng Pháp nếu tôi không nhầm.
Darkhogg

4
@Darkoose: Latin1 thực sự không dành riêng cho tiếng Anh, nhưng về cơ bản nó bị giới hạn trong bảng chữ cái Tây Âu.
Bart van Ingen Schenau

16
Lợi ích duy nhất có thể có từ việc sử dụng tiếng Latin 1 thay vì UTF-8 trong một hệ thống hiện đại là phá hoại. Điều đó tất nhiên chỉ là một lợi ích cho kẻ phá hoại, và bất cứ ai trung thành với họ, không phải cho chủ sở hữu hoặc nhà phát triển của hệ thống.
Jon Hanna

13
Quá tệ, cơ sở dữ liệu của bạn sẽ không thể giữ biểu tượng Euro hoặc thậm chí tên của tôi (ד TOUR).
dotancohen

20
người dùng "sao chép và dán" các ký tự không phải là Latin-1? đừng coi unicode là một thứ phù phiếm không liên quan mà chỉ những người mọt sách tinh quái mới quan tâm. khá nhiều người trong chúng ta loại các ký tự không phù hợp với tiếng Latin-1 một cách thường xuyên - tôi nghe thấy rất nhiều người nói các ngôn ngữ ngoài châu Âu, thậm chí ♥
Eevee

Câu trả lời:


131

Unicode chắc chắn là khó khăn và mã hóa UTF-8 có một vài thuộc tính bất tiện. Tuy nhiên, UTF-8 đã trở thành mã hóa tiêu chuẩn thực tế trên web, vượt qua ASCII, Latin-1, UCS-2 và UTF-16. Chỉ cần sử dụng UTF-8 ở mọi nơi .

Lý do quan trọng nhất khiến bạn nên hỗ trợ Unicode là bạn không nên đưa ra các giả định không cần thiết về đầu vào của người dùng. Tôi không biết tên miền của bạn là gì, nhưng những thứ như tên người dùng tiếng Do Thái, một bài đăng trên blog về Trung Quốc, một bình luận với Emoji, hoặc đơn giản là văn bản được tạo kiểu tốt - như là điều này, nên có thể là Oh Oh, đó là những dấu ngoặc kép chính xác ( “”thay vì ""), dấu gạch ngang rộng và dấu chấm lửng, là các ký tự phổ biến trong văn bản tiếng Anh, nhưng không được ASCII hoặc Latin-1 hỗ trợ. Vì vậy, việc không hỗ trợ các tập lệnh khác không chỉ là một vấn đề lớn đối với các nền văn hóa khác, nhưng việc gắn bó với tiếng Latin-1 thậm chí không cho phép bạn viết tiếng Anh đúng.

Quan niệm rằng Unicode chỉ cho phép các ký tự xấu của Viking là sai. Có, văn bản thực sự phức tạp và Unicode sẽ không che giấu điều đó khỏi bạn. Sếp của bạn có thể đang suy nghĩ về các ký tự sáng tác, trong đó một điểm mã cơ sở như ađược sửa đổi bởi các điểm mã tiếp theo, ví dụ đại diện cho dấu phụ để tạo thành một ký tự trực quan như á. Điều này không thực sự cản trở bạn khi cố gắng thực hiện tìm kiếm nếu bạn thực hiện một số loại chuẩn hóa. Ví dụ: bạn có thể lưu trữ tất cả văn bản ở dạng NFC, thu gọn các bố cục đó thành dạng được phân tách sẵn nếu chúng có sẵn. Khi thực hiện tìm kiếm, bạn cũng có thể loại bỏ tất cả các ký tự soạn thảo khỏi văn bản, nhưng điều này có thể thay đổi đáng kể ý nghĩa của chúng trong một số ngôn ngữ.

Unicode cũng thêm rất nhiều ký tự không thể in được - nhưng ngay cả ASCII cũng có vô số ký tự. Bạn sẽ xử lý một NUL ở giữa một chuỗi? Làm thế nào về 0x1C, một bộ phân tách tập tin trên mạng? Tôi chưa bao giờ thấy một nửa trong số đó . Latin-1 thêm một dấu gạch nối mềm cho biết cơ hội phá vỡ từ, nhưng nếu không thì vô hình. Điều đó cũng phá vỡ tìm kiếm toàn văn của bạn? Nói cách khác, ngay cả ASCII và Latin-1 cũng cho phép bạn phá vỡ hoàn toàn đầu vào của mình nếu bạn cho rằng tất cả chỉ là văn bản có thể in được!


8
Từ góc độ cơ sở dữ liệu, một số ký tự đó không / không được phép trong trường loại văn bản (văn bản / varchar / char / vv.). MySQL không cho phép các ký tự null trong các loại dữ liệu này, nhưng các cơ sở dữ liệu khác như PostgreSQL thì không. Bạn nên sử dụng BLOB (MySQL) hoặc BYTEA (PostgreSQL) nếu bạn muốn lưu trữ các ký tự đó.
cimmanon

15
"Bám sát Latin-1 thậm chí không cho phép bạn viết tiếng Anh đúng" Đó là một điều tốt, nếu không thì unicode sẽ bị kháng cự mạnh hơn nữa. ;-)
Ded repeatator

3
@ PaŭloEbermann Các ký tự NUL được nhúng có nghĩa là dữ liệu của bạn là một blob nhị phân, không chỉ là một chuỗi. NUL là một ví dụ kỳ lạ, vì tôi tin rằng UTF-8 tránh sử dụng \0byte như một phần của mã hóa nhiều byte, để đảm bảo mã không nhận biết UTF8 không dừng ở giữa chuỗi.
Peter Cordes

7
Tất cả các ký tự unicode đều có thể in được - bạn chỉ cần đúng phông chữ :-)
James Anderson

4
@JamesAnderson phông chữ sau đó sẽ bị sai và bị hỏng. vi.wikipedia.org/wiki/Unicode_control_char
character

62

Tôi nghĩ ngoài câu hỏi kỹ thuật, sếp của bạn có thể không có thời gian để cập nhật các tiêu chuẩn hiện tại.

Vì lập trường của anh ấy không hoàn toàn ra ngoài ăn trưa, chỉ là lỗi thời, tôn trọng vị trí của anh ấy khi thảo luận về vấn đề này (và bạn cần nhớ thảo luận , không tranh luận), và cố gắng giải quyết những lo ngại mà anh ấy có liên quan đến UTF-8. Tôi nghi ngờ vấn đề cơ bản không phải là vấn đề kỹ thuật và có thể yêu cầu một số mức độ đàm phán kỹ năng mềm.


6
Tôi không thể chấp thuận nhiều hơn. Thật ra tôi rất tiếc rằng trong câu trả lời của riêng tôi, tôi đã hoàn toàn bỏ qua "khía cạnh con người", trong vấn đề này có thể là tối quan trọng. Ước gì tôi có thể nâng cao hơn một lần :-)
LSerni

2
gọi tất cả mọi thứ bên ngoài latin-1 bad charactervà nghĩ rằng đây non-printablejust out-datedvới bạn?
njzk2 2/2/2015

2
Vấn đề thực sự là, "Đây có phải là vấn đề kỹ thuật mà chúng ta đang giải quyết không?" Tôi không tin rằng ông chủ của OP đã đến trường và được dạy điều này, hoặc đọc một số hướng dẫn kỹ thuật / tạp chí và đi đến kết luận đó. Tôi không hiểu rằng giải pháp này hoàn toàn là một giải pháp kỹ thuật. Trớ trêu thay, bình luận cho thấy chính xác trọng tâm của vấn đề; giải quyết vấn đề này có thể cực kỳ gây khó chịu nếu làm không đúng cách.
Nelson

49

Ai trong chúng ta đúng?

Ngày xửa ngày xưa, sếp của bạn là vậy. Nhưng thời gian trôi qua, mọi thứ thay đổi. Ngày nay, bạn là (nhưng trước khi chạy đến sếp của bạn, hãy chắc chắn đọc câu trả lời của Nelson quá ).

Các phiên bản cũ của MySQL và các phiên bản cũ của hầu hết mọi thứ , xử lý tốt hơn nhiều so với Latin1 / ISO-8859-1 (5) cũ hơn so với UTF8.

Có một lý do tại sao UTF8 đã được tạo ra, phát triển và được đẩy hầu hết ở mọi nơi: nếu được thực hiện đúng cách, nó hoạt động tốt hơn nhiều . Có một số vấn đề về hiệu năng và lưu trữ xuất phát từ thực tế là ký tự Latin1 là 8 bit, trong khi ký tự UTF8 có thể dài từ 8 đến 32 bit. Vì vậy, khi lập kế hoạch VARCHARbạn cần phải tính đến điều này. thói quen tìm kiếm của bạn sẽ chậm hơn một chút. Họ sẽ có thể làm nhiều việc hơn (ví dụ: các tìm kiếm có độ nhạy hoặc không có . Không thể thực hiện những điều đó trong Latin1 mà không cần làm việc nhiều), nhưng họ sẽ mất thêm một chút thời gian.

Nhưng mặt khác, dung lượng lưu trữ rẻ , chi phí thực tế trên kích thước tệp nhỏ hơn 2-3%, khả năng tính toán cũng rẻ và ngày càng rẻ hơn theo Luật Moore; trong khi thời gian của bạnsự mong đợi của khách hàng chắc chắn là không .

Bạn có thể phải lo lắng cho các công cụ tìm kiếm, vv nếu bạn là người phát triển các công cụ đó. Nhưng có lẽ bạn không. Bạn sử dụng những công cụ đó; ngay cả những người không hoàn toàn tuân thủ UTF8 ngày hôm qua (như các MySQL trước đó không có), sẽ sớm có ngày hôm nay (ví dụ: MySQL có hỗ trợ utf8mb4).

Vì vậy, bằng cách lập kế hoạch cẩn thận và triển khai UTF8 đúng cách ( không phải tát nó qua Latin1 như một cách suy nghĩ lại), bạn có thể có mã chứng minh tương lai rất hợp lý , nếu bạn dự định kinh doanh với bất kỳ quốc gia châu Á nào, thì rất tốt Điều. Và nếu bạn không có kế hoạch như vậy, những người khác sẽ có, và những người đó có thể là khách hàng, nhà cung cấp hoặc đối tác của bạn.

Vì vậy, khi họ bắt đầu gửi cho bạn dữ liệu UTF8, bạn sẽ phải thiết lập một điều phức tạp để chuyển đổi sang fro Latin1 và xử lý các trường hợp không thể giải quyết.

Khi bạn tính đến ngân sách, chi phí của một vài cuộc giao tranh chống lại các ninja mojibake độc ​​ác và xem xét rằng chúng sẽ không biến mất - như bạn đã phát hiện ra - sau đó bạn sẽ nhận ra rằng việc đi UTF8 không chỉ đơn giản hơn, nó sẽ trở nên đơn giản hơn rẻ hơn là tốt


4

Một số tình huống giới hạn ký tự chỉ được đặt thành ASCII có thể có ý nghĩa đối với các trường lựa chọn hạn chế, ví dụ như trường trạng thái, vì bạn kiểm soát chặt chẽ các giá trị có thể có và khóa ngoại / tham chiếu đến hệ thống bên ngoài, vì hiếm khi có bất kỳ lý do nào cho chúng có bất cứ thứ gì ngoại trừ các ký tự chữ và số và một vài ký hiệu.

Đối với bất kỳ văn bản nào khác, chỉ cần sử dụng UTF-8.


2
MySQL không có enums?
raptortech97 2/2/2015

2
Và vì ASCII là tập con của UTF8, nên chỉ cần sử dụng UTF8 ngay cả sau đó.
RemcoGerlich 2/2/2015

@RemcoGerlich: Tôi không đồng ý rằng bạn có thể sử dụng UTF8 cho những người đó. Theo quan điểm của tôi, các tham chiếu bên ngoài không phải là văn bản mà là chuỗi byte mờ đục. Họ không có bộ ký tự ngoại trừ sự thuận tiện công chứng. Nếu chuỗi byte có một cách hiểu trong bộ ký tự nhất định, đó là miền của hệ thống bên ngoài hoặc của ứng dụng, không phải của cơ sở dữ liệu.
Lie Ryan

3
@LieRyan: Tôi thấy điểm đó, nhưng sau đó không phải là ASCII, có thể là một số định dạng blob nhị phân hoặc như vậy.
RemcoGerlich 2/2/2015

3

Để bắt đầu với câu trả lời, không quan trọng, máy chủ của bạn được cấu hình như thế nào . Mã hóa ký tự trong MySQL có thể được cấu hình trên mỗi cột (có nghĩa là, cùng một bảng có thể giữ các ký tự trong nhiều bảng mã, dễ dàng). Tức là máy chủ của tôi (và một số cơ sở dữ liệu cũ) được cấu hình cho cp1251 theo mặc định cho các máy khách cũ không thể đặt đối chiếu chính xác khi kết nối (các máy khách phần cứng khác nhau), nhưng tất cả các cơ sở dữ liệu chính trong sản xuất đều sử dụng UTF-8.

Nói về "không gian lãng phí" - thực tế bạn không thể gọi dữ liệu quan trọng là lãng phí, phải không? Tuy nhiên, việc tăng dung lượng lưu trữ sẽ khác nhau tùy thuộc vào ngôn ngữ mà dữ liệu của bạn được sử dụng. Từ mức tăng không đáng kể (dưới 1%) nếu trang web của bạn chủ yếu bằng tiếng Anh và lên đến 100%, nếu đó là thư sử dụng các ký tự bên ngoài phạm vi ASCII . Và thậm chí nhiều hơn, nếu bạn di chuyển Firther phía đông. Các thông số kỹ thuật UTF-8 (được gọi là UTF8mb4) sau này cho phép tối đa 4 byte cho mỗi điểm mã.

Và đối với "ai đúng" thì Sự thật là, đây là một câu hỏi xã hội nhiều hơn là kỹ thuật. Có thể có lý do hợp lệ cho các thiết lập máy chủ cụ thể, nhưng bạn phải biết ý nghĩa này. Nhưng nếu bạn hỏi tôi, không có lý do gì để không sử dụng UTF-8. Đó là một loại để cai trị tất cả các văn bản trên thế giới.


MySQL sẽ cố gắng chuyển đổi dữ liệu trong mã hóa Cơ sở dữ liệu trước khi chuyển đổi sang mã hóa cột. Nếu bạn có máy khách utf8, cơ sở dữ liệu latin1 và utf8 columnt, thì dữ liệu văn bản có thể bị mất.
Ivan Solntsev 2/2/2015

Ivan, đó là một câu hỏi hoàn toàn khác. Sự xen kẽ giữa bộ ký tự-máy khách, bộ ký tự-máy chủ, kết nối bộ ký tự, bộ ký tự-kết quả là một bài viết dài trong tài liệu MySQL. Và trong trường hợp cài đặt đối chiếu trên mỗi cột, "đối chiếu cơ sở dữ liệu" là đối chiếu cột và nó được chuyển đổi trực tiếp thành kết quả thiết lập ký tự, bỏ qua đối chiếu cơ sở dữ liệu.
AnrDaemon

0

Chỉ cần giải thích với anh ta rằng UTF-8 là mặc định cho lưu lượng truy cập web. Và bất kỳ người dùng nào cũng có thể nhập bất kỳ ký tự unicode hợp lệ nào trong trình duyệt của họ.

Nó dễ dàng hơn nhiều để có utf-8 / unicode suốt từ đầu đến cuối cuối so với việc giải quyết nhiều vấn đề khác nhau và kết quả từ utf-8-> latin-1-> utf-8.

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.