A collation defines alphabetical order for a language: it is what makes ORDER BY behave the way a reader expects. For utf8mb4, MySQL 8.0.46 ships eighty-nine of them. For the whole of Southeast Asia it ships exactly one.

utf8mb4_vietnamese_ci

That is the complete list. No Thai, no Khmer, no Lao, no Burmese. For those languages your database does not have a wrong answer about alphabetical order — it has no answer, and returns codepoint order while calling it ORDER BY.

Six names, five collations, four different orders

Start with Vietnamese, which is the one that is catered for. Six surnames, sorted five ways:

general_ci      An  Ánh  Dương  Nguyễn  Trần  Đặng
unicode_ci      An  Ánh  Dương  Đặng  Nguyễn  Trần
vietnamese_ci   An  Ánh  Dương  Đặng  Nguyễn  Trần
0900_ai_ci      An  Ánh  Đặng  Dương  Nguyễn  Trần
bin             An  Dương  Nguyễn  Trần  Ánh  Đặng

The disagreement is about Đ, which in Vietnamese is a letter in its own right, ordered after D. Each collation has a different theory:

unicode_ci, vietnamese_ci   Đ after D          — the Vietnamese answer
0900_ai_ci                  Đ folded into D    — Đặng before Dương
general_ci                  Đ after everything — it lands last, past T
bin                         byte order         — every accented name last

Note which row is which. utf8mb4_0900_ai_ci is MySQL 8's default, and it is the one that disagrees with utf8mb4_vietnamese_ci. If you created your table without saying otherwise, you have the accent-insensitive answer: sensible for search, wrong for a list of names, and never announced.

Pay closest attention to general_ci. A decade of tutorials recommended it, so a great many older tables still carry it. It sorts Đặng after Trần — past the end of the alphabet, where nobody scrolling a name list will think to look.

Thai does not have a wrong answer available

Thai writes five of its vowels before the consonant they are pronounced after. เ, แ, โ, ใ and ไ sit to the left of their consonant on the page, and Thai dictionary order keys on the consonant, not on the character that happens to be written first.

The result is that Thai is sorted by a character that does not determine the word's alphabetical position:

MySQL, any available collation:   กิน  นก  เด็ก  แม่  ไทย
Thai dictionary order:            กิน  เด็ก  ไทย  นก  แม่

Three of the five words are filed under the wrong letter: เด็ก ("child") belongs under ด, ไทย ("Thai") under ท, and แม่ ("mother") under ม, but each is filed under its leading vowel instead. Because those three move, four of the five end up in a different position — นก is displaced without being misfiled. The leading-vowel words cluster together in a block at the end, in an order no reader recognises.

This is not a defect that a better collation setting fixes, because there is no Thai collation to select. It is a job that has to be done above the database, by a library that knows the language, or not at all.

The measurement was wrong the first time

This mistake is worth recording because the output it produced was so confident. The first run of this comparison sorted Vietnamese names into an order that made no sense — Đặng first, ahead of An — under two collations at once.

The data was double-encoded. The MySQL client had been given a UTF-8 file without --default-character-set=utf8mb4, so it announced the bytes as latin1 and the server re-encoded them into UTF-8 a second time. The table contained the mojibake of Vietnamese rather than Vietnamese.

CHAR_LENGTH('Đặng')  reported 7   should be 4
HEX('Đặng')          C384C290...  should be C490...

Every ordering in that first run was real, reproducible, and meaningless. The check that catches it costs one query — count the characters in a word you know the length of — and the harness now runs it before anything else, because a sort order over the wrong bytes looks exactly like a sort order.

Where a wrong order actually reaches people

Sorting is easy to dismiss as cosmetic, which is why these bugs survive. The consequences are real:

a name list someone scrolls   the entry is not where they look for it
autocomplete ordering          the right answer sits below the fold
pagination                     a row can appear on two pages, or on none
"starts with" filters          an index tab that is empty or overfull
deduplication by neighbour     near-duplicates never become adjacent

The pagination one is the least obvious and the most damaging. If two parts of a system order the same rows under different collations — the query that counts and the query that fetches, or an application-side sort layered over a database one — then the boundary between page one and page two falls in two different places, and rows slip through the gap. Nothing errors. A record simply cannot be found by browsing, and can still be found by searching, which makes it look like a caching problem.

Checking your own is three queries:

1. SHOW TABLE STATUS / information_schema.columns  → what collation is it actually using?
2. sort a handful of names you know the correct order for
3. SELECT CHAR_LENGTH on a word whose length you know → is the data even encoded correctly?

Run the third one first. If it disagrees with you, the other two are measuring the wrong bytes and will produce orderings that look plausible and mean nothing.

What to do

Vietnamese      utf8mb4_vietnamese_ci, set explicitly on the column
mixed content   sort in the application, with a library that has CLDR data
Thai and others no database answer exists — sort above it, or do not claim to
anywhere        never rely on the default; name the collation in the schema

A collation is a claim about a language. The default is a claim about no language in particular. It is a fine default for matching and a poor one for presenting a list to somebody who knows how their own alphabet works.

If you cannot sort correctly, it is better to sort by something you can defend — creation order, frequency, a number — than to present codepoint order as alphabetical. The second is wrong and looks authoritative.

How this was measured, and what it does not settle

MySQL 8.0.46 in Docker, six Vietnamese surnames and five Thai words, ordered under each named collation, with the connection charset set explicitly and an encoding assertion run first. The collation inventory is from information_schema.collations on that server.

Six names is enough to show the orders differ and not enough to characterise a collation. utf8mb4_unicode_ci and utf8mb4_vietnamese_ci produced identical output here, which does not mean they agree in general — a larger set including the vowel variants Ă and  would be needed to separate them.

The Thai comparison uses the orthographic rule about leading vowels rather than a published sort key, and the five test words were chosen specifically to exercise it. A Thai speaker checking a real dictionary is the better authority than this measurement, and would find the same three words moved.

Other databases differ. PostgreSQL delegates to the operating system's locale data or to ICU, which does have Thai collation, so the same query on the same data can be right there and wrong here. That is the difference between your data being unsortable and your engine's inventory being short.