Your problem is that your SET NAMES 'utf8_persian_ci'
command was invalid (utf8_persion_ci is a collation, not an encoding). If you run it in a terminal you will see an error Unknown character set: 'utf8_persian_ci'
. Thus your application, when it stored the data, was using the latin1
character set. MySQL interpreted your input as latin1 characters which it then stored encoded as utf-8. Likewise when the data was pulled back out, MySQL converted it from UTF-8 back to latin1 and (hopefully, most of the time) the original bytes you gave it.
In other words, all your data in the database is completely messed up, but it just so happened to work.
To fix this, you need to undo what you did. The most straightforward way is using PHP:
SET NAMES latin1;
- Select every single text field from every table.
SET NAMES utf8;
- Update the same rows using the same string unaltered.
Alternatively you can perform these steps inside MySQL, but it's tricky because MySQL understands the data to be in a certain character set. You need to modify your text columns to a BLOB type, then modify them back to text types with a utf8 character set. See the section at the bottom of the ALTER TABLE
MySQL documentation labeled "Warning" in red.
After you do either one of these things, the bytes stored in your database columns will be the actual character set they claim to be. Then, make sure you always use mysql_set_charset('utf8')
on any database access from PHP that you may do in the future! Otherwise you will mess things up again. (Note, do not use a simple mysql_query('SET NAMES utf8')
! There are corner cases (such as a reset connection) where this can be reset to latin1
without your knowledge. mysql_set_charset()
will set the charset whenever necessary.)
It would be best if you switched away from mysql_*
functions and used PDO
instead with the charset=utf8
parameter in your PDO dsn.