安装
虽然Linux有yum install,但事情往往不会这么顺利。当你执行安装命令的时候,可能会提示你 找不到装源,或者安装了一个很低的版本。想装最新的就得自己动手。 以Centos 7 为例
添加安装源
可以下载并安装MySQL官方的 Yum Repository
wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm yum -y install mysql57-community-release-el7-10.noarch.rpm yum -y install mysql-community-server 复制代码
可以采用yum localinstall
命令来添加 MySQL 源。在 dev.mysql.com/downloads/r… 页面选择合适 rpm 包,这些 rpm 包的作用就是添加 MySQL yum 源的。笔者下载的是 mysql80-community-release-el7-1.noarch.rpm。点下载后会跳到另一个页面,让你注册账号。反正我是没注册,因为在页面最下面,有一个链接 No thanks, just start my download. 可以直接下载。
执行安装启动
安装的时候一路 y 就行了。
sudo yum install mysql-community-server #启动 systemctl start mysqld.service #老版本的启动 sudo service mysqld start #查看状态 systemctl status mysqld.servic #关闭 systemctl stop mysqld.service 复制代码
修改密码
mysql早期的版本的默认密码是空字符串。后来mysql觉得这样会有安全隐患(其实没什么不安全的,只是用户太懒,不修改密码,才导致不安全),所以一装好就设置了一个超复杂的密码,相当于示范:密码就应该设成这样。
#查看默认密码 grep 'temporary password' /var/log/mysqld.log 复制代码
执行查看命令后会输出
A temporary password is generated for root@localhost: AjShNajwD4=c
AjShNajwD4=c 就是mysql 生成的默认密码。
然后我们通过这个密码连数据库
mysql -u root -p 复制代码
执行完命令后会提示输密码,把AjShNajwD4=c输入回车就连上数据库了。 或者直接把密码放在后面,但要注意要紧贴着-p
中间不能有空格 这时就可以做任意操作了。第一个要做的就是修改密码
ALTER USER 'root'@'localhost' IDENTIFIED BY '123'; 复制代码
本来想设个简单的密码练习用。没想到因为太简单被拒了 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
所以练习还是用低版本吧。
远程连接
首先确认 主机是否已经开启 8360端口。可能还需要到主机服务商提供的后台去手动打开端口 MySQL 安装后,默认只开放本机连接,为了支持其他主机连接,可以通过修改表mysql的host字段来实现。host ='%'
的意思是 允许任何host 通过 root 用户访问 在shell下执行 mysql -u root -p
use mysql; update user set host = '%' where user = 'root'; flush privileges; 复制代码
也可以这样写
GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host'; grant all privileges on *.* to root@'%' identified by "123456"; 复制代码
个人觉得修改mysql表更直观一些。 不过如果没有必要,最好不要开放远程链接,为了安全着想。
mysql8 执行了上面语句可能还不好用。还需要执行
alter user 'root'@'%' identified with mysql_native_password by 'passWord'
注意'root'@'%'
最开始的时候应该是'root'@'localhost'
选择数据表类型
执行 show engines
会发现 InnoDB 为默认表类型。
sudo /etc/my.cnf 复制代码
打开my.cnf 增加 default-storage-engine=MyISAM 保存,重新mysql 服务,会现 MyISAM已经变成默认表类型了。
解决中文乱码
- 修改mysql配置文件/etc/my.cnf
[mysqld] character-set-server=utf8 [client] default-character-set=utf8 [mysql] default-character-set=utf8 复制代码
- 建表的时候指定 utf8编码
create table user( id char(32), name varchar(10) ) default charset=utf8 复制代码
做到这两条就可以正常使用中文了。 如果你一开始就修改了my.conf文件,建表的时候不用再指定 default charset=utf8
但如果你是在建完数据库后修改的配置文件,可能需要明确指定 charset
。 一般来说,总是加在 default charset=utf8
好些。
使用中可能遇到的问题
安装好以后,就可以使用了。
字段长度超出
Mysql 数据有个特点,当insert 的字段度超出时且不符合保留条件时不会报错,而是直接把它截掉。 比如 对于这样一个 user 表
名称 | type |
name | char(2) |
执行语句 insert into user values('令胡冲')
mysql不会报错,会直接舍掉冲字,只把 “令胡” 两个字存起来。
可以给字段扩大长度
alter table user modify column name varchar(10) 复制代码
timestamp 数据类型
mysql版本不同,处理这个字段的方式会不同,这里以 V5.1为例说明。
哪个版本怎么处理不重要,重要的是知道mysql处理这个字段的会特殊一点就行了,因为可以随时查文档。
create table user( updateTime TIMESTAMP not null, createTime TIMESTAMP not null, } 复制代码
给user 表建两个 TIMESTAMP类型的字段,mysql 会把第一个设置为 default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
。在新建和更新的时候,mysql 都会自动用当前时间戳设置或更新这个字段。不过一个表中只有一个字段可以有这样的待遇,第二个 TIMESTAMP
类型的字段不能自动处理,需要手动处理。
另外,插入时间类型字段的时候,如果不能直接插入毫秒,可以按这个格式插入 0000-00-00 00:00:00
mysql8 中实测,一个表中可以有两个字段 default 值为 TIMESTAMP
关于外键
外键这个问题一直有争议,但是技术本身没有对错之分,重要的是用在适合的场合。 但是如何算是“用在适合的场合”?这个太难,所以出现了太多 外键被滥用的情形。
外键优点
- 在数据库的层面严格保证数据的完整性。
最主要的优点其实就这一条。但是缺点有好几条。
- 更新性能降低
- 逻辑分散,相当于把业务逻辑分散到了数据层,或复制到了数据层。
- 不方便测试。增加了生成测试数据的成本。
越是对于海量级的应用,越是倾向于不在数据库中用外键,只在业务逻辑中保证即可。数据库保持简单,目的纯粹,只做存储即可。
在mysql 早期版本中默认用的是 MyISAM 表类型,不支持外键。但是需要注意的 MyISAM 只是简单的忽略外键约束,并不报错。所以如果你不知道这一点,很可能被搞晕。要想支持外键可以用 innoDB 表类型。
查看表类型
show create table user; #结果中包括 ENGINE=MyISAM ,说明是MyISAM类型 复制代码
修改表类型
#修改 use表的类型为 InnoDB; alter table use type=InnoDB; 复制代码
或者在建表的时候直接指定
create table user (name varchar(10)) type=myisam; 复制代码
还可以修改配置文件
关于事务
同样的 MyISAM 不支持事务。为什么?因为凡事都有代价,支持事务也是以性能为代价的。
如果对数据一致性要求不是很高,可以不用事务。比如一个操作要更新两个表,可以分别更新两个表。如果发生不一致,先不管,然后可以定期集中修复一下数据不一致的问题。如果数据只是临时的而且有不一致也是可以接受的,那就不用管。
如果对一致性要求很高,那就必须用事务或其它方式来保证一致性。处理事务,需要注意的是,一个事务中的语句不要并发,需要顺序执行。 node 中用 await
正合适
事务分四种隔离级别:读未提交 ,读提交,可重得读,串行化。mysql 默认是可重复读。
--老版写法,新版mysql 已经不再支持 SELECT @@tx_isolation --新版写法 select @@transaction_isolation; --新版中还可以模糊查询 show variables like 'transaction_%' 复制代码
查询结果是 REPEATABLE-READ
可重得读的意思是一个事务中的第一条select
语句执行的时候,会建立 一个select_view
,整个事务结束前都会从这时读数据,数据都是不变的。如何做到不变呢,视图本身并没有数据,就是通过回滚日志对当前的数据进行回滚。所以如果事务时间过长,会导致需要保留的回滚日志和视图过多,所以要避免长事务。
查询长事务
--新版才能用,多长算长事务,自己定 select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>30 复制代码
四种隔离级别,读未提交不建视图,直接读最新内容,一般是从内存中读。读提交 是只能读已经commit的提交。方法是在每条语句执行时建立视图。 串行化不用视图,直接锁定。
常用语句
CREATE DATABASE dbame drop database dbname use dbname create table user(id char(32)) default charset=utf8 type=myisam; drop table user alter table user add column name char(5) //列增加后不能删除 insert into table1(field1,field2) values(value1,value2) insert into values(value1,value2) update table1 set field1=value1 where select * from user limit 1,10 select count(*) from user;//myIsAM类型的表对这个语句有优化,直接给结果。不用扫描表 describe user; show tables; show databases; select version(); 复制代码
删除 unique 约束的时候,可能不知道unique的名称,这时需要先查询再删除
show create table tableName; alter table drop index indexName; 复制代码
unique
约束也可以叫叫唯一索引,除了保证唯一也可以提高访问速度.从删除语句 可以看出,和普通索引一样,只是创建时不同index
来定义 普通索引,普通索引可以不唯一,可以加快搜索速度primary
主键索引,唯一,并且是查询速度最快的,尽量用主键查询.
新加列的时候,默认列值是允许 null的 ,新播入的值是 null 新加列如果指定 not null 新播入的值是对应数据类型的默认值 ,比如 tinyint 的默认值 是0 如果指定 not null default xx 新播入的值 就是 xx 如果指定 default xx 没有指定 not null 新加列的值也是 xx
如果把 允许null 的列修改为不允许为null,原来的null值会变成 空值。
limit start,end
要放在最后, 从第一条记录开始的3条记录 limit 0,3
或 limit 3
数据备份
mysqldump -u root -p databasename > back.sql 复制代码
有人说可以这样恢复 mysqldump -u root -p databasename < back.sql 反正我试了好多次没有成功, 可以这样恢复 ,先连上数据库,执行 source 命令source back.sql
(需要绝对路径) 不过需要保证数据库存在,并已经 use database,不然还是无法恢复的。 恢复是原理 是先drop table,然后重建,通过执行语句来恢复数据。
当数据量不大的时候,每次都全最备份,有问题,就全量恢复。但是全量恢复不是把备份恢复了就完事了,还有备份后发生的更改呢?这就需要 binlog。binlog是server层面的日志,与存储引擎无关。可以把备份时间点到现在的更改重做,这样就可以完全恢复了。当然了,由于数据有误,可能 会导致后面的数据更新也是错误的,所以需要结合业务来确定要恢复哪些,不恢复哪些。
如何使用 null 值
在建表的时候,可以指定 null,not noll。
- null: 如果不指定输入值,将会把null 播入
- not null: 如果不指定输入值,将会把空值 播入
null和空的区别。
- null占存储空间,空间不占空间
- null表示无意义,空值有意义,值是空值而已
- count(columnName) 是不会把null算进来的,不过如果是count(*),只要有一列的值不为null,就会计算在内。
在应用中,用null,还是空值应该更加注重语义,而不是为了方便。
timestamp默认值问题
createt T ( createTime timestamp not null ) 复制代码
在mysql 5.1中如果这样建表,实际上等价于这样建表
createt T ( createTime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) 复制代码
可以用 show create table T
来进行验证
本来createTime的原意是创建时间,但现在更新数据的时候createTime也会更新,这样与语义不符。所以建表的时候,应该把值都加上,避免默认值引起的问题。