MySQL杂谈第一部分:root密码重置、乱码问题、主从备份、表情符支持、常见问题等。
重置root密码
忘记MySQL root用户密码时可以用下面的方法找回:
- 取决于系统注册服务的方式,选择一个命令停止MySQL服务:
service mysqld stop # init.d systemctl stop mysql.service # systemd
- 用下面的命令重启
mysqld_safe --skip-grant-tables &
- 以
root
用户身份免密码进入MySQL终端并修改密码mysql -u root mysql
- 进入MySQL终端后,重置
root
用户密码(将new_pwd
换成你的新密码)use mysql; update user set password=password('new_pwd') where user='root'; flush privileges; exit;
- 重启MySQL服务器
service mysqld stop # init.d systemctl start mysql.service # systemd
乱码问题
出现乱码一般是因为服务器不支持当前字符(比如用ascii编码集存中文),或服务器编码与连接编码不一致。[如果是web应用,还应该先检查下当前应用默认编码是否正确(对于Java应用可通过JVM参数-Dfile.encoding=UTF8
设置)。]
遇到乱码时,首先要确认服务器的默认编码已正确设置:
show variables where variable_name like 'character%';
返回如下查询结果:
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
如果发现默认编码有问题,修改my.cnf
,记得修改后要重启MySQL服务:
[mysqld]
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
在MySQL终端里测试是否还有乱码现出,必要时用下面的命令修改本次session使用的编码,以utf8为例:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
程序里出现乱码时,通常只需要在Jdbc连接参数添加useUnicode=true
即可解决,以HickariCP为例:
HikariConfig#setJdbcUrl(".....&useUnicode=true")
当我们的数据库使用的不是my.cnf
配置的默认编码时,在建立连接时应先调用SET names xxx
,比如:
HikariConfig#setConnectionInitSql("SET names utf8mb4")
主从备份
注意:本节内容只适用于使用InnoDB
的数据库。
创建主从备份的步骤,
- 在主库上运行(将
db_host, db_user
分别换成你的主库IP,用户名。db1, db2, db3
是需要备份的数据库的名字。
如果出现mysqldump -h'db_host' -u'db_user' --quick --routines --master-data=2 --single-transaction --databases db1 db2 db3 > mydb.dump
mysqldump: Error: Binlogging on server not active
则可能是你的主库还没有启用binlog
。这时需要修改主库的my.cnf
文件,在[mysqd]
部分添加如下配置server-id = 1 log_bin = /var/log/mysql/mysql-bin.log
- 在从库上导入数据库。
mysql -h'slave_db' -u'slave_db_user' -p < mydb.dump
- 修改从库的
my.cnf
文件,在[mysqld]
下面增加server-id=2
。注意其值必须与主库或其它从库的不一样。重新加载配置sudo service mysql reload
。 - 在主库上授权:
grant replication slave on *.* to username@'x.x.x.x' identified by 'xxxx'; flush privileges;
- 在从库上启动备份:打开之前导出的备份文件
mydb.dump
,找到CHANGE MASTER TO
一行,如-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=107;
- 使用主库的信息补全这个命令,并在从库上执行:
change master to master_log_file='mysql-bin.000001',master_log_pos=107,master_host='x.x.x.x', master_port=xxx,master_user='xxx',master_password='xxx';
- 在从库启动备份
slave start
- 检查从库的备份状态
show slave status\G;
主键、唯一键与外键
建立主键、唯一键与外键约束也就意味着建立了索引。用show index from mytable;
查看某个表上的索引。
唯一键创建与删除
-- 创建
alter table t1 add constraint uk_mf_rf unique key (rtfile);
-- 删除方法1
alter table t1 drop index uk_t1_rf;
-- 删除方法2
drop index uk_t1_rf on t1;
外键创建与删除
注意删除时要执行两条命令,若只执行drop foreign key
那么原来的外键列变为普通索引列。
-- 创建
alter table t2 add constraint fk_test_mid foreign key (mid) references t1(id);
-- 删除
alter table t2 drop foreign key fk_test_mid;
alter table t2 drop index fk_test_mid;
自增主键重用问题
自增主键重用是指删除数据后,新生成的主键与之前删除的主键相同。服务器重启时就有可能出现这种情况,所以要尽量避免使用如下的语句移动数据:
insert trgt_table select * from src_table d where ....
让MySQL支持表情符 - 将数据库类型转换为utf8mb4
MySQL的utf8并不能表示所有的UTF8字符集,比如这个符号:👽
。解决办法是使用utf8mb4
表示字符串。下面介绍如何修改,使utf8mb4
成为默认字符集。
- 修改数据库、表格、字符串类型字段的编码。
-- 修改数据库的编码 alter database mydb character set = utf8mb4 collate = utf8mb4_unicode_ci; -- 修改表格的编码 alter table mydb convert to character set utf8mb4 collate utf8mb4_unicode_ci; -- 修改字段的编码 alter table mydb change summary summary text character set utf8mb4 collate utf8mb4_unicode_ci;
- 修改
my.cnf
[mysqld] character_set_client_handshake = FALSE character_set_server = utf8mb4 collation_server = utf8mb4_unicode_ci [client] default_character_set = utf8mb4 [mysql] default_character_set = utf8mb4
- 使用
service mysql restart
重启MySQL服务后,在MySQL终端里查看是否修改成功:show variables where variable_name like 'character\_set\_%' or variable_name like 'collation%';
- 最后不要忘记修复数据库:
mysqlcheck -u root -p --auto-repair --optimize --all-databases
注1: 使用utf8mb4编码后,导出数据库时最好给mysqldump加上--default-character-set=utf8mb4
参数。
注2: 实际应用中,往往只需要让一个字段支持全UTF8字符集,
- 这时只需要修改此字段的字符集:
alter table mydb change summary summary text character set utf8mb4 collate utf8mb4_unicode_ci;
- 然后在连接数据库时,指定默认编码:
SET names utf8mb4
关于数据库连接池
创建数据库连接池的注意事项:
- 如果系统即有耗时的数据库操作,也有许多短暂的数据库操作,最好创建两个独立的连接池。
- 如果系统有许多耗时的数据库操作,通常会在应用里使用队列限流。连接池的大小应该与这个队列的大小匹配。
常见问题与错误处理
mysqldump含有binary或blob类型的数据库
如果数据库含有binary
或blob
等类型的字段,在导出时应该给mysqldump加上--hex-blob
参数。否则导出的sql会出现乱码,导入时也可能出现错误。
mysqldump --hex-blob --default-character-set=utf8mb4 --single-transaction -h xx.xx.xx.xx mydb -r mydb.dump
MySQL 1449 Error: The user specified as a definer...
这个问题通常因为导入含有trigger/procedure的数据库时,创建者不存在引起的。导入数据库后建立需要的用户即可:
grant all on *.* to 'my_user'@'%' identified by 'my_pwd'; flush privileges;
character与collation的区别
可以通过MySQL命令show character set;
查看服务器支持的所有字符集(character set
)与对应的默认collation
。
character
表示字符编码,含有中文的数据库通常会使用utf8
或utf8mb4
。utf8mb4
最多可使用4个字节表示一个字符,而utf8
最多可使用3个字节表示一个字符。collation
用于定义MySQL对比字符串的规则,常见的有三种:_general
表示按字符比较,区分大小写;_genearal_ci
表示按字符比较,不区分大小写;_bin
表示按字节比较,通常用于只需要判断等或不等的字段。
限制访问
修改my.cnf
,设置允许访问的客户端IP:bind-address=your-host-ip
。如果MySQL服务器暴露在外网,强烈建议使用此配置增强安全性。