MySql记录的一些使用方法和经验
Posted xinxi2010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql记录的一些使用方法和经验相关的知识,希望对你有一定的参考价值。
MySql记录的一些使用方法和经验
MySQL数据库最初由瑞典的Tomas Ulin、Allan Larsson和Michael Widenius创立。后来,该公司被SUN Microsystems购买了,然后在2008年被Oracle购买。Oracle是一个主要提供商的商业数据库公司,这意味着MySQL现在是由Oracle控制并拥有的。
然而,MySQL用户担心他们的数据库软件会像其他被收购的开源数据库软件一样,被Oracle停止支持。为了避免这种情况发生,一个名为“MariaDB”的分支项目被启动了。它由MySQL的创始人Michael Widenius领导,旨在维护MySQL的开源性和自由性。这个项目后来发展成为了MariaDB数据库。由于MariaDB是自由和开源的,所以MySQL的用户可以安心地迁移到MariaDB,以获得更好、更可靠、更自由的数据库体验。我们鼓励MySQL用户尽可能快地迁移到MariaDB。
MariaDB使用与MySQL相同的命令和语法,因此,对于MySQL用户来说,迁移到MariaDB应该是比较容易的。MariaDB是自由和开源的,不像MySQL那样由一个商业数据库公司控制和拥有。这使得MariaDB在确保开源性和自由性方面比MySQL更好。
一、MySql安装
下载地址:https://dev.mysql.com/downloads/
在安装MySql之前,查看是否以及安装过MySql,如果已经安装,但是不符合要求的话就卸载。
如果是windows安装的话,下载windows的安装包,一路next下去,设置好账号和密码就行了。
1,查找以前是否装有mysql
先输入:
rpm -qa|grep -i mysql
查看是否安装了mysql
2,停止mysql服务、删除之前安装的mysql
输入:
ps -ef|grep mysql
删除命令
输入:
rpm -e –nodeps 包名
如果提示依赖包错误,则使用以下命令尝试
rpm -ev 包名 --nodeps
如果提示错误:error: %preun(xxxxxx) scriptlet failed, exit status 1
则用以下命令尝试:
rpm -e --noscripts 包名
3、查找并删除mysql目录
查找结果如下:
find / -name mysql
删除对应的mysql目录
具体的步骤如图:查找目录并删除
注意:卸载后/etc/my.cnf不会删除,需要进行手工删除
4、再次查找机器是否安装mysql
rpm -qa|grep -i mysql
Mysql有两种安装模式,可自行选择。
1.1 yum安装
首先查看mysql 是否已经安装
输入:
rpm -qa | grep mysql
如果已经安装,想删除的话
输入:
普通删除命令:
rpm -e mysql
强力删除命令:
rpm -e --nodeps mysql
依赖文件也会删除
安装mysql
输入:
yum list mysql-server
如果没有,则通过wget命令下载该包
输入:
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
下载成功之后,再输入命令安装
yum install mysql-server
在安装过程中遇到选择输入y就行了
安装成功后,输入 service mysqld start 启动服务
输入:
mysqladmin -u root -p password \'123456\'
来设置密码
输入之后直接回车(默认是没有密码的)
然后再输入
mysql -u root -p
通过授权法更改远程连接权限
输入: grant all privileges on . to \'root\'@\'%\' identified by \'123456\';
注:第一个’root’是用户名,第二个’%’是所有的ip都可以远程访问,第三个’123456’表示 用户密码 如果不常用 就关闭掉
输入:flush privileges; //刷新
在防火墙关闭之后,使用SQLYog之类的工具测试是否能正确连接
1.2 编译包安装
将下载好的mysql安装包上传到linux服务器
解压mysql解压包,并移动到/usr/local目录下,重命名为mysql。
命令:
tar -xvf mysql-5.6.21-linux-glibc2.5-x86_64.tar.gz
mv mysql-5.6.21-linux-glibc2.5-x86_64 /usr/local
cd /usr/local
mv mysql-5.6.21-linux-glibc2.5-x86_64 mysql
注: mysql默认的路径是就是/usr/local/mysql ,如果安装的地方更改,需要更改相应的配置文件。
安装mysql
切换到mysql的目录 /usr/local/mysql
输入:
./scripts/mysql_install_db --user=mysql
成功安装mysql之后,输入
service mysql start 或 /etc/init.d/mysql start
查看是否启动成功
输入:
ps -ef|grep mysql
切换到 /usr/local/mysql/bin 目录下
设置密码
mysqladmin -u root password \'123456\'入mysql
输入:
mysql -u root -p
设置远程连接权限
输入:
grant all privileges on *.* to \'root\'@\'%\' identified by \'123456\';
然后输入:
flush privileges;
说明: 第一个’root’是用户名,第二个’%’是所有的ip都可以远程访问,第三个’123456’表示用户密码 如果不常用就关闭掉。
使用本地连接工具连接测试
二、MySql排查问题的常用命令
1.查看mysql连接数
SHOW FULL PROCESSLIST;
2.查看mysql的配置
show variables like "%innodb%";
3.查看mysql事件是否开启
show variables like \'event_scheduler\';
4.查看mysql锁的状态
是否锁表:
SHOW OPEN TABLES WHERE In_use > 0;
SHOW INNODB STATUS/G;
5.查看mysql data的存放位置
SHOW VARIABLES LIKE \'%datadir%\'
6.查看mysql 的超时时间设置
show variables like \'%timeout%\';
7.查看mysql 的日志存放
show variables like \'datadir\';
mysql的日志分类
错误日志: -log-err
查询日志: -log
慢查询日志: -log-slow-queries
更新日志: -log-update
二进制日志: -log-bin
8.开启Mysql的操作日志记录
输入:
SHOW VARIABLES LIKE \'log_bin\'
开启错误日志:
在my.cnf 或my.ini 中 添加 log-error=/home/mysql/logs/log-error.txt
开启查询日志:
在my.cnf 或my.ini 中 添加 log=/home/mysql/logs/mysql_log.txt
9.查看Mysql缓冲池大小
SHOW GLOBAL VARIABLES LIKE \'innodb_buffer_pool_size\';
10.当前目录赋予mysql权限
chown -R mysql:mysql ./
11.查看mysql脏页比例
USE performance_schema;
SELECT VARIABLE_VALUE INTO @a FROM global_status WHERE VARIABLE_NAME = \'Innodb_buffer_pool_pages_dirty\';
SELECT VARIABLE_VALUE INTO @b FROM global_status WHERE VARIABLE_NAME = \'Innodb_buffer_pool_pages_total\';
SELECT @a/@b;
要合理的设置 innodb_io_capacity 的值,平时要多关注脏页比例,不让其接近 75%.
可以通过 innodb_flush_neighbors 来控制该行为,值为 1 打开上述机制,为 0 则关闭。
对于机械硬盘来说,是可以减少很多随机 IO ,因为机械硬盘 IOPS 一般就几百,减少随机 IO 就意味着性能提升。
但如果用 SSD 这类 IOPS 较高的设备,IOPS 往往不是瓶颈,关闭就好,减少 SQL 语句的响应时间。
在 8.0 中,已经默认是 0 了.
12.查看慢查询以及开启
SHOW VARIABLES LIKE \'slow_query%\';
SET GLOBAL slow_query_log=ON;
set global long_query_time=1;
永久设置
[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 1
long_query_time表示查询超过多少秒就记录
13. 开启mysql查询日志
开启会降低性能
查看日志配置
SHOW VARIABLES LIKE \'%general_log%\';
查询文件输出格式
SHOW VARIABLES LIKE \'log_output\';
开启MySQL查询日志
SET GLOBAL general_log = ON;
关闭MySQL查询日志
SET GLOBAL general_log = OFF;
设置日志输出方式为表
SET GLOBAL log_output=\'table\';
查询日志信息
select * from mysql.general_log;
14.数据库慢或数据库连接过多的命令排查
按客户端 IP 分组,看哪个客户端的链接数最多
SELECT client_ip,COUNT(client_ip) AS client_num FROM (SELECT
SUBSTRING_INDEX(HOST,\':\' ,1) AS client_ip FROM PROCESSLIST ) AS
connect_info GROUP BY client_ip ORDER BY client_num DESC;
查看正在执行的线程,并按 Time 倒排序,看看有没有执行时间特别长的线程
SELECT * FROM information_schema.processlist WHERE Command != \'Sleep\'
ORDER BY TIME DESC;
找出所有执行时间超过 5 分钟的线程,拼凑出 kill 语句,方便后面查杀
SELECT CONCAT(\'kill \', id, \';\') FROM information_schema.processlist
WHERE Command != \'Sleep\' AND TIME > 300 ORDER BY TIME DESC;
批量kill的语句
select concat(\'KILL \',a.trx_mysql_thread_id ,\';\') from INFORMATION_SCHEMA.INNODB_LOCKS b,INFORMATION_SCHEMA.innodb_trx a where b.lock_trx_id=a.trx_id into outfile \'/tmp/kill.txt\';
三、MySql的优化建议
1.建表建议
1.1 选择索引的数据类型
MySQL支持很多数据类型,选择合适的数据类型存储数据对性能有很大的影响。通常来说,可以遵循以下一些指导原则:
1.越小的数据类型通常更好:
越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。
2.简单的数据类型更好:
整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址。
3.尽量避免NULL:
应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
4.一个表的索引最好不要超过6个:
索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引
1.2 选择主键类型
选择合适的标识符是非常重要的。选择时不仅应该考虑存储类型,而且应该考虑MySQL是怎样进行运算和比较的。一旦选定数据类型,应该保证所有相关的表都使用相同的数据类型。
- 整型:
通常是作为标识符的最好选择,因为可以更快的处理,而且可以设置为AUTO_INCREMENT。 - 字符串:
尽量避免使用字符串作为标识符,它们消耗更好的空间,处理起来也较慢。而且,通常来说,字符串都是随机的,所以它们在索引中的位置也是随机的,这会导致页面分裂、随机访问磁盘,聚簇索引分裂(对于使用聚簇索引的存储引擎)。
Mysql常见索引有:主键索引、唯一索引、普通索引、全文索引、组合索引
PRIMARY KEY(主键索引) ALTER TABLE table_name
ADD PRIMARY KEY ( col
)
UNIQUE(唯一索引) ALTER TABLE table_name
ADD UNIQUE (col
)
INDEX(普通索引) ALTER TABLE table_name
ADD INDEX index_name (col
)
FULLTEXT(全文索引) ALTER TABLE table_name
ADD FULLTEXT ( col
)
组合索引 ALTER TABLE table_name
ADD INDEX index_name (col1
, col2
, col3
)
Mysql各种索引区别:
普通索引:最基本的索引,没有任何限制
唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
主键索引:它 是一种特殊的唯一索引,不允许有空值。
全文索引:仅可用于 MyISAM 表,针对较大的数据,生成全文索引很耗时好空间。
联合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。创建复合索引时应该将最常用(频率)作限制条件的列放在最左边,依次递减。
联合索引的好处:覆盖索引,这一点是最重要的,众所周知非主键索引会先查到主键索引的值再从主键索引上拿到想要的值。但是覆盖索引可以直接在非主键索引上拿到相应的值,减少一次查询。
复合索引和普通索引都是用一棵B+树表示的。
如果是单列,就按这列key数据进行排序。
如果是多列,就按多列数据排序,
例如有(1,1)(1,4)(2,2)(1,3) (2,1)(1,2)(2,3) (2,4)
那在索引中的叶子节点的数据顺序就是(1,1)(1,2)(1,3) (1,4)(2,1)(2,2)(2,3) (2,4)
这也是为什么查询复合索引的前缀是可以用到索引的原因
1.3 mysql索引方法hash和Btree区别
Hash仅支持=、>、>=、<、<=、between。BTree可以支持like模糊查询
索引是帮助mysql获取数据的数据结构。最常见的索引是Btree索引和Hash索引。
不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引;而Mermory默认的索引是Hash索引。
我们在mysql中常用两种索引算法BTree和Hash,两种算法检索方式不一样,对查询的作用也不一样。
一、BTree
BTree索引是最常用的mysql数据库索引算法,因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上,而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量,例如:
select * from user where name like ‘jack%’;
select * from user where name like ‘jac%k%’;
如果一通配符开头,或者没有使用常量,则不会使用索引,例如:
select * from user where name like ‘%jack’;
select * from user where name like simply_name;
二、Hash
Hash索引只能用于对等比较,例如=,<=>(相当于=)操作符。由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引。
但为什么我们使用BTree比使用Hash多呢?主要Hash本身由于其特殊性,也带来了很多限制和弊端:
1.Hash索引仅仅能满足“=”,“IN”,“<=>”查询,不能使用范围查询。
2.联合索引中,Hash索引不能利用部分索引键查询。
对于联合索引中的多个列,Hash是要么全部使用,要么全部不使用,并不支持BTree支持的联合索引的最优前缀,也就是联合索引的前面一个或几个索引键进行查询时,Hash索引无法被利用。
3.Hash索引无法避免数据的排序操作
由于Hash索引中存放的是经过Hash计算之后的Hash值,而且Hash值的大小关系并不一定和Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算。
4.Hash索引任何时候都不能避免表扫描
Hash索引是将索引键通过Hash运算之后,将Hash运算结果的Hash值和所对应的行指针信息存放于一个Hash表中,由于不同索引键存在相同Hash值,所以即使满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要通过访问表中的实际数据进行比较,并得到相应的结果。
5.Hash索引遇到大量Hash值相等的情况后性能并不一定会比BTree高
对于选择性比较低的索引键,如果创建Hash索引,那么将会存在大量记录指针信息存于同一个Hash值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据访问,而造成整体性能底下。
- hash索引查找数据基本上能一次定位数据,当然有大量碰撞的话性能也会下降。而btree索引就得在节点上挨着查找了,很明显在数据精确查找方面hash索引的效率是要高于btree的;
- 那么不精确查找呢,也很明显,因为hash算法是基于等值计算的,所以对于“like”等范围查找hash索引无效,不支持;
- 对于btree支持的联合索引的最优前缀,hash也是无法支持的,联合索引中的字段要么全用要么全不用。提起最优前缀居然都泛起迷糊了,看来有时候放空得太厉害;
- hash不支持索引排序,索引值和计算出来的hash值大小并不一定一致。
1.4 mysql不走索引的情况
-
数据量太少:
如果表中的行数很少,MySQL可能会选择全表扫描而不是使用索引。 -
索引列被函数处理:
如果查询中对索引列进行了函数处理,MySQL就无法使用该索引进行优化,例如:
SELECT * FROM table WHERE YEAR(date_column) = 2021;
将无法使用date_column上的索引进行优化。
- 索引列被类型转换:
如果查询中对索引列进行了类型转换,MySQL也无法使用该索引进行优化,例如:
SELECT * FROM table WHERE int_column = \'1\';
将无法使用int_column上的索引进行优化。
-
索引列被模糊查询:
如果查询中对索引列进行了模糊查询(如使用LIKE, 非左匹配),MySQL也无法使用该索引进行优化。 -
多列索引未使用前缀:
如果使用了多列索引,并且查询中只使用了其中的一部分列,但是没有使用前缀,MySQL也无法使用该索引进行优化。 -
索引列存在NULL值:
如果索引列存在NULL值,MySQL可能无法使用该索引进行优化。 -
查询条件中包含OR、NOT、IN以及子查询的情况。
-
使用联合索引但是查询条件顺序不正确。
-
left join 字符集不一致
这种情况并非常见 可以通过以下语句查看: SHOW FULL COLUMNS FROM table1; SHOW FULL COLUMNS FROM table2;
2.查询优化建议
通过关键字 EXPLAIN 在查询语句前面加上可以查看索引走向
从上到下,性能从差到好
- all 全表查询
- index 索引全扫描
- range 索引范围扫描
- ref 使用非唯一或唯一索引的前缀扫描,返回相同值的记录
- eq_ref 使用唯一索引,只返回一条记录
- const,system 单表中最多只有一行匹配,根据唯一索引或主键进行查询
- null 不访问表或索引就可以直接得到结果
优化建议:
-
JOIN 后的的条件必须是索引,最好是唯一索引,否则数据一旦很多会直接卡死
-
一般禁止使用UNIION ON,除非UNION ON 前后的记录数很少
-
禁止使用OR
-
查总数使用COUNT(*)就可以,不需要COUNT(ID),MYSQL会自动优化
-
数据库字段设置 NOT NULL,字段类型 INT > VARCHAR 越小越好
-
禁止SELECT * ,需要确定到使用的字段
-
一般情况不在SQL中进行数值计算
3. 总数查询优化 建议
1.如果未设置主键,也未设置索引,可以对整型的字段添加索引
2.通过一个中间表来记录数据库内各表记录总数,然后通过触发器进行监听该表,实时更新总条数.
触发器:
CREATE
TRIGGER 数据库名
.触发器名
BEFORE/AFTER INSERT/UPDATE/DELETE
ON 数据库名
.<Table Name>
FOR EACH ROW
BEGIN
事件发生后执行的代码
END
创建示例:
当test_count表添加了数据,就对MT_COUNT的总数进行更新。
DELIMITER $$
CREATE
TRIGGER `ROWS_COUNT` BEFORE INSERT
ON `test_count`
FOR EACH ROW BEGIN
UPDATE MT_COUNT SET rowcount=rowcount+1 WHERE tablename = \'test_count\';
END$$
DELIMITER ;
3.分页查询只第一次查询总数,或者分页查询和总数查询分开。
4.提升MySql写入速度建议
innodb_buffer_pool_size
如果用Innodb,那么这是一个重要变量。相对于MyISAM来说,Innodb对于buffer
size更敏感。MySIAM可能对于大数据量使用默认的key_buffer_size也还好,但Innodb在大数据量时用默认值就感觉在爬了。
Innodb的缓冲池会缓存数据和索引,所以不需要给系统的缓存留空间,如果只用Innodb,可以把这个值设为内存的70%-80%。和
key_buffer相同,如果数据量比较小也不怎么增加,那么不要把这个值设太高也可以提高内存的使用率。
innodb_additional_pool_size
这个的效果不是很明显,至少是当操作系统能合理分配内存时。但你可能仍需要设成20M或更多一点以看Innodb会分配多少内存做其他用途。
innodb_log_file_size
对于写很多尤其是大数据量时非常重要。要注意,大的文件提供更高的性能,但数据库恢复时会用更多的时间。一般用64M-512M,具体取决于服务器的空间。
innodb_log_buffer_size
默认值对于多数中等写操作和事务短的运用都是可以的。如
果经常做更新或者使用了很多blob数据,应该增大这个值。但太大了也是浪费内存,因为1秒钟总会
flush(这个词的中文怎么说呢?)一次,所以不需要设到超过1秒的需求。8M-16M一般应该够了。小的运用可以设更小一点。
innodb_flush_log_at_trx_commit (这个很管用)
抱怨Innodb比MyISAM慢
100倍?那么你大概是忘了调整这个值。默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。特别是使用电
池供电缓存(Battery backed up
cache)时。设成2对于很多运用,特别是从MyISAM表转过来的是可以的,它的意思是不写入硬盘而是写入系统缓存。日志仍然会每秒flush到硬
盘,所以你一般不会丢失超过1-2秒的更新。设成0会更快一点,但安全方面比较差,即使MySQL挂了也可能会丢失事务的数据。而值2只会在整个操作系统
挂了时才可能丢数据。
四、MySql遇到的问题以及解决办法
1. mysql离线安装出现:Can\'t change to run as user \'mysql\' ; Please check that the user exists!
原因:没有该用户。
解决办法:创建该用户!
例如:
添加用户:
groupadd -g 315 mysql
用户加入mysql:
useradd -u 315 -g mysql -d /usr/local/mysql -M mysql
再次输入
./scripts/mysql_install_db --user=mysql
成功!
2,安装完mysql之后,输入service mysql start 提示 mysql: unrecognized service。
问题原因: 是因为/etc/init.d/ 不存在 mysql 这个命令,所以无法识别。
解决办法:
1.首先查找mysql.server文件在哪
输入:
find / -name mysql.server
2.将mysql.server 复制到/etc/init.d/目录下,并重命名为mysql或mysqld
输入:
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
3.测试是否可以使用该命令
输入:
service mysql status
或
service mysqld status
3. 打开mysql出现:Got error 28 from storage engine
原因:mysql服务器的存储空间不够了,清空不用的数据就可以使用了。
4. Data too long for column 异常
1.数据库中设置的字符长度不够
找到对应的字段,将字符长度加长一些。
2.编码导致的原因,一般是由于输入了中文,才会出现类似的错误
统一设置为UTF-8
5. Can\'t connect to local MySQL server through socket \'/tmp/mysql.sock\' (2)
登录出现此异常
原因: 没有找到该文件,可以在/etc/my.cnf 文件中确认该文件的位置,若确定,这查看此文件的权限,若权限也ok,则添加 软链,
例如:
ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock
若还不行,则通过 mysql -uroot -p -S /var/run/mysqld/mysqld.sock 直接登录,不输入密码 。登录成功之后,在通过添加软链重新启动。
6. 登录mysql报错-bash: mysql: 未找到命令
原因:这是由于系统默认会查找/usr/bin下的命令,如果这个命令不在这个目录下,当然会找不到命令,我们需要做的就是映射一个链接到/usr/bin目录下,相当于建立一个链接文件。
首先得知道mysql命令或mysqladmin命令的完整路径,比如mysql的路径是:/usr/local/mysql/bin/mysql,我们则可以这样执行命令:
ln -s /usr/local/mysql/bin/mysql /usr/bin
以下是补充:
linux下,在mysql正常运行的情况下,输入mysql提示:
mysql command not found
遇上-bash: mysql: command not found的情况别着急,这个是因为/usr/local/bin目录下缺失mysql导致,只需要一下方法建立软链接,即可以解决:
把mysql安装目录,比如MYSQLPATH/bin/mysql,映射到/usr/local/bin目录下:
cd /usr/local/bin
ln -fs /MYSQLPATH/bin/mysql mysql
还有其它常用命令mysqladmin、mysqldump等不可用时候都可按用此方法解决。
注:其中MYSQLPATH是mysql的实际安装路径。
7. initialize specified but the data directory has files in it. Aborting
报这个错误的原因是因为你的mysql数据库已经进行初始化了,所以不能用这种方式再进行初始化用户了,因为mysql在初始化的时候会自动创建一个root用户的。更改/etc/cnf 的配置就行。
8.The server quit without updating PID file
错误信息详细描述:
root@MyServer:~# service mysql start
Starting MySQL
..The server quit without updating PID file (/usr/local/mysql/var/MyServer.pid). ... failed!
错误解决排查思路:
1.可能是/usr/local/mysql/data/rekfan.pid文件没有写的权限
解决方法 :给予权限,执行 “chown -R mysql:mysql /var/data” “chmod -R 755 /usr/local/mysql/data” 然后重新启动mysqld!
2.可能进程里已经存在mysql进程
解决方法:用命令“ps -ef|grep mysqld”查看是否有mysqld进程,如果有使用“kill -9 进程号”杀死,然后重新启动mysqld!
3.可能是第二次在机器上安装mysql,有残余数据影响了服务的启动。
解决方法:去mysql的数据目录/data看看,如果存在mysql-bin.index,就赶快把它删除掉吧,它就是罪魁祸首了。
4.mysql在启动时没有指定配置文件时会使用/etc/my.cnf配置文件,请打开这个文件查看在[mysqld]节下有没有指定数据目录(datadir)。
解决方法:请在[mysqld]下设置这一行:datadir = /usr/local/mysql/data
5.skip-federated字段问题
解决方法:检查一下/etc/my.cnf文件中有没有没被注释掉的skip-federated字段,如果有就立即注释掉吧。
6.错误日志目录不存在
解决方法:使用“chown” “chmod”命令赋予mysql所有者及权限
7.selinux惹的祸,如果是centos系统,默认会开启selinux
解决方法:关闭它,打开/etc/selinux/config,把SELINUX=enforcing改为SELINUX=disabled后存盘退出重启机器试试。
9.Failed to start mysql.service: Unit not found. Mysql
systemctl list-unit-files --type=service | grep mysql
service mysqld.service start
10.mysqldump: Got error: 1045: Unknown error 1045 when trying to connect
添加双引号
11.mysql 写入生僻字或特殊字符错误的解决办法
问题: 插入SQ语句出现 Incorrect string value: \'\\xF0\\xA1\\x8B\\xBE\\xE5\\xA2...\' for column \'name\',这种错误,数据库编码设置已经是utf-8 ,插入其他的非特殊字符的语句正确。
解决办法 : mysql 版本5.5.3以后,有了一个utf8mb4编码,是utf8的超集,也兼容unicode 。所以将编码格式改为这个就可以了。
在my.cnf或my.ini中添加:
[client]
default-character-set = utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4
其他
参考:
http://blog.csdn.net/zq199692288/article/details/78863737
https://blog.csdn.net/hjf161105/article/details/78850658
https://blog.csdn.net/everda/article/details/77476716
http://blog.itpub.net/29654823/viewspace-2150471
关于sql相关的文章:
https://www.cnblogs.com/xuwujing/category/1081197.html
非常好听的音乐~
mysql索引一些思考
B+树索引的使用经验(大范围)
- 已经知道数据库中存在两种类型的应用,
OLTP
和OLAP
应用。 - 在
OLTP
应用中,查询操作只从数据库中取得一小部分数据,一般可能都在10
条记录以下,甚至在很多时候只取1条记录,如根据主键值来取得用户信息,根据订单号取得订单的详细信息,这都是典型OLTP应用的查询语句。在这种情况下,B+树索引建立后,对该索引的使用应该只是通过该索引取得表中少部分的数据。这时建立B+树索引才是有意义的,否则即使建立了,优化器也可能选择不使用索引。 - 对于
OLAP
应用,情况可能就稍显复杂了。不过概括来说,在OLAP
应用中,都需要访问表中大量的数据,根据这些数据来产生查询的结果,这些查询多是面向分析的查询,目的是为决策者提供支持。如这个月每个用户的消费情况,销售额同比、环比增长的情况。因此在OLAP中索引的添加根据的应该是宏观的信息
,而不是微观,因为最终要得到的结果是提供给决策者的。例如不需要在OLAP中对姓名字段进行索引,因为很少需要对单个用户进行查询。但是对于OLAP中的复杂查询,要涉及多张表之间的联接操作,因此索引的添加依然是有意义的。但是,如果联接操作使用的是Hash Join,那么索引可能又变得不是非常重要了,所以这需要DBA或开发人员认真并仔细地研究自己的应用。不过在OLAP应用中,通常会需要对时间字段进行索引,这是因为大多数统计需要根据时间维度来进行数据的筛选。
B+树索引的管理
索引的创建和删除可以通过两种方法,一种是ALTER TABLE,另一种是CREATE/DROP INDEX。若用户想要查看表中索引的信息,可以使用命令SHOW INDEX
。
- Table:索引所在的表名。
- Non_unique:非唯一的索引,可以看到primary key是0,因为必须是唯一的。
- Key_name:索引的名字,用户可以通过这个名字来执行DROP INDEX。
- Seq_in_index:索引中该列的位置,如果看联合索引idx_a_c就比较直观了。
- Column_name:索引列的名称。
- Collation:列以什么方式存储在索引中。可以是A或NULL。B+树索引总是A,即排序的。如果使用了Heap存储引擎,并且建立了Hash索引,这里就会显示NULL了
索引管理 - FIC (Fast Index Creation)
MySQL 5.5版本之前(不包括5.5)存在的一个普遍被人诟病的问题是MySQL数据库对于索引的添加或者删除的这类DDL操作,MySQL数据库的操作过程为:
- 首先创建一张新的临时表,表结构为通过命令ALTER TABLE新定义的结构(创建索引)。
- 然后把原表中数据导入到临时表。
- 接着删除原表。
- 最后把临时表重名为原来的表名。 可以发现,若用户对于一张大表进行索引的添加和删除操作,那么这会需要很长的时间。更关键的是,若有大量事务需要访问正在被修改的表,这意味着数据库服务不可用。
InnoDB存储引擎从InnoDB 1.0.x版本开始支持一种称为Fast Index Creation
(快速索引创建)的索引创建方式——简称FIC。 对于辅助索引的创建,InnoDB存储引擎会对创建索引的表加上一个S锁
。在创建的过程中,不需要重建表,因此速度较之前提高很多,并且数据库的可用性也得到了提高。删除辅助索引操作就更简单了,InnoDB存储引擎只需更新内部视图,并将辅助索引的空间(内存)标记为可用(你随时使用这块空间,我现在这块空间没人使用了)
,同时删除MySQL数据库内部视图上对该表的索引定义
由于FIC在索引的创建的过程中对表加上了S锁,因此在创建的过程中只能对该表进行读操作
,若有大量的事务需要对目标表进行写操作,那么数据库的服务同样不可用。此外,FIC方式只限定于辅助索引,对于主键的创建和删除同样需要重建一张表。
索引管理 - OSC(Online Schema Change)
Online Schema Change(在线架构改变,简称OSC)最早是由Facebook实现的一种在线执行DDL
的方式,并广泛地应用于Facebook的MySQL数据库。所谓“在线”是指在事务的创建过程中,可以有读写事务
对表进行操作,这提高了原有MySQL数据库在DDL操作时的并发性
。Facebook采用PHP脚本
来现实OSC,而并不是通过修改InnoDB存储引擎源码的方式。OSC最初由Facebook的员工Vamsi Ponnekanti开发。此外,OSC借鉴了开源社区之前的工具The openarkkit toolkit oak-online-alter-table。实现OSC步骤如下:
- init,即初始化阶段,会对创建的表做一些验证工作,如检查表是否有主键,是否存在触发器或者外键等。
- createCopyTable,创建和原始表结构一样的新表。
- alterCopyTable:对创建的新表进行ALTER TABLE操作,如添加索引或列等。
- createDeltasTable,创建deltas表,该表的作用是为下一步创建的触发器所使用。之后对原表的所有DML操作会被记录到createDeltasTable中。
- createTriggers,对原表创建INSERT、UPDATE、DELETE操作的触发器。触发操作产生的记录被写入到deltas表。
- startSnpshotXact,开始OSC操作的事务。
- selectTableIntoOutfile,将原表中的数据写入到新表。为了减少对原表的锁定时间,这里通过分片(chunked)将数据输出到多个外部文件,然后将外部文件的数据导入到copy表中。分片的大小可以指定,默认值是500 000。
- dropNCIndexs,在导入到新表前,删除新表中所有的辅助索引。
- loadCopyTable,将导出的分片文件导入到新表。
- replayChanges,将OSC过程中原表DML操作的记录应用到新表中,这些记录被保存在deltas表中。
- recreateNCIndexes,重新创建辅助索引。
- replayChanges,再次进行DML日志的回放操作,这些日志是在上述创建辅助索引中过程中新产生的日志。
- swapTables,将原表和新表交换名字,整个操作需要锁定2张表,不允许新的数据产生。由于改名是一个很快的操作,因此阻塞的时间非常短。
索引管理 - Online DDL
虽然FIC可以让InnoDB存储引擎避免创建临时表,从而提高索引创建的效率。但正如前面小节所说的,索引创建时会阻塞表上的DML操作。OSC虽然解决了上述的部分问题,但是还是有很大的局限性。MySQL 5.6版本开始支持Online DDL(在线数据定义)操作,其允许辅助索引创建的同时,还允许其他诸如INSERT、UPDATE、DELETE这类DML操作,这极大地提高了MySQL数据库在生产环境中的可用性。
此外,不仅是辅助索引,以下这几类DDL操作都可以通过“在线”的方式进行操作:
- 辅助索引的创建与删除
- 改变自增长值
- 添加或删除外键约束
- 列的重命名
通过新的ALTER TABLE语法,用户可以选择索引的创建方式:
ALTER TABLE tbl_name
|ADDINDEX|KEY[index_name]
[index_type](index_col_name,...)[index_option]...
ALGORITHM[=]DEFAULT|INPLACE|COPY
LOCK[=]DEFAULT|NONE|SHARED|EXCLUSIVE
ALGORITHM指定了创建或删除索引的算法,COPY表示按照MySQL 5.1版本之前的工作模式,即创建临时表的方式。INPLACE表示索引创建或删除操作不需要创建临时表。DEFAULT表示根据参数old_alter_table来判断是通过INPLACE还是COPY的算法,该参数的默认值为OFF,表示采用INPLACE的方式
LOCK部分为索引创建或删除时对表添加锁的情况,可有的选择为:
(1)NONE 执行索引创建或者删除操作时,对目标表不添加任何的锁,即事务仍然可以进行读写操作,不会收到阻塞。因此这种模式可以获得最大的并发度。
(2)SHARE 这和之前的FIC类似,执行索引创建或删除操作时,对目标表加上一个S锁。对于并发地读事务,依然可以执行,但是遇到写事务,就会发生等待操作。如果存储引擎不支持SHARE模式,会返回一个错误信息。
(3)EXCLUSIVE 在EXCLUSIVE模式下,执行索引创建或删除操作时,对目标表加上一个X锁。读写事务都不能进行,因此会阻塞所有的线程,这和COPY方式运行得到的状态类似,但是不需要像COPY方式那样创建一张临时表。
(4)DEFAULT DEFAULT模式首先会判断当前操作是否可以使用NONE模式,若不能,则判断是否可以使用SHARE模式,最后判断是否可以使用EXCLUSIVE模式。也就是说DEFAULT会通过判断事务的最大并发性来判断执行DDL的模式。
InnoDB存储引擎实现Online DDL的原理是在执行创建或者删除操作的同时,将INSERT、UPDATE、DELETE这类DML操作日志写入到一个缓存中。待完成索引创建后再将重做应用到表上,以此达到数据的一致性。这个缓存的大小由参数innodb_online_alter_log_max_size控制,默认的大小为128MB。
用户更新的表比较大,并且在创建过程中伴有大量的写事务,如遇到innodb_online_alter_log_max_size的空间不能存放日志时,会抛出类似如下的错误:
Error:1799SQLSTATE:HY000(ER_INNODB_ONLINE_LOG_TOO_BIG) Message:Creating index’idx_aaa’required more than’innodb_online_alter_log_max_size’bytes of modification log.Please try again.
对于这个错误,用户可以调大参数innodb_online_alter_log_max_size
,以此获得更大的日志缓存空间。此外,还可以设置ALTER TABLE的模式为SHARE,这样在执行过程中不会有写事务发生,因此不需要进行DML日志
的记录。 需要特别注意的是,由于Online DDL在创建索引完成后再通过重做日志达到数据库的最终一致性,这意味着在索引创建过程中,SQL优化器不会选择正在创建中的索引。
Cardinality值
并不是在所有的查询条件中出现的列都需要添加索引
。对于什么时候添加B+树索引,一般的经验是,在访问表中很少一部分时使用B+树索引才有意义。对于性别字段、地区字段、类型字段,它们可取值的范围很小,称为低选择性。
如: SELECT*FROM student WHERE sex=‘M’ 按性别进行查询时,可取值的范围一般只有’M’、‘F’。因此上述SQL语句得到的结果可能是该表50%的数据(假设男女比例1∶1),这时添加B+树索引是完全没有必要的。
相反,如果某个字段的取值范围很广,几乎没有重复,即属于高选择性,则此时使用B+树索引是最适合的。例如,对于姓名字段,基本上在一个应用中不允许重名的出现。
怎样查看索引是否是高选择性的呢?可以通过SHOW INDEX
结果中的列Cardinality
来观察。Cardinality值非常关键,表示索引中不重复记录数量的预估值。同时需要注意的是,Cardinality是一个预估值,而不是一个准确值,基本上用户也不可能得到一个准确的值。在实际应用中,Cardinality/n_rows_in_table应尽可能地接近1。如果非常小,那么用户需要考虑是否还有必要创建这个索引。故在访问高选择性属性的字段并从表中取出很少一部分数据时,对这个字段添加B+树索引是非常有必要的
因为MySQL数据库中有各种不同的存储引擎,而每种存储引擎对于B+树索引的实现又各不相同,所以对Cardinality的统计是放在存储引擎层
进行的。数据库对于Cardinality的统计都是通过采样(Sample)
的方法来完成的。
在InnoDB存储引擎中,Cardinality统计信息的更新发生在两个操作中:INSERT和UPDATE。根据前面的叙述,不可能在每次发生INSERT和UPDATE时就去更新Cardinality信息,这样会增加数据库系统的负荷,同时对于大表的统计,时间上也不允许数据库这样去操作。
InnoDB存储引擎内部对更新Cardinality信息的策略为:
- 表中1/16的数据已发生过变化。
- stat_modified_counter>2 000 000 000。
第一种策略为自从上次统计Cardinality信息后,表中1/16的数据已经发生过变化,这时需要更新Cardinality信息。第二种情况考虑的是,如果对表中某一行数据频繁地进行更新操作,这时表中的数据实际并没有增加,实际发生变化的还是这一行数据,则第一种更新策略就无法适用这这种情况。故在InnoDB存储引擎内部有一个计数器stat_modified_counter,用来表示发生变化的次数,当stat_modified_counter大于2 000 000 000时,则同样需要更新Cardinality信息。
InnoDB存储引擎内部是怎样来进行Cardinality信息的统计和更新操作的呢?同样是通过采样的方法。默认InnoDB存储引擎对8个叶子节点(Leaf Page)进行采用。采样的过程如下:
- 取得B+树索引中叶子节点的数量,记为A。
- 随机取得B+树索引中的8个叶子节点。统计每个页不同记录的个数,即为P1,P2,…,P8。
- 根据采样信息给出Cardinality的预估值:Cardinality=(P1+P2+…+P8)*A/8。
通过上述的说明可以发现,在InnoDB存储引擎中,Cardinalit值是通过对8个叶子节点预估而得的,不是一个实际精确的值。
在InnoDB 1.2版本之前,可以通过参数innodb_stats_sample_pages用来设置统计Cardinality时每次采样页的数量,默认值为8。同时,参数innodb_stats_method用来判断如何对待索引中出现的NULL值记录。该参数默认值为nulls_equal,表示将NULL值记录视为相等的记录。其有效值还有nulls_unequal,nulls_ignored,分别表示将NULL值记录视为不同的记录和忽略NULL值记录。
InnoDB1.2版本提供了更多的参数对Cardinality统计进行设置,这些参数如表
Multi-Range Read优化
MySQL5.6版本开始支持Multi-Range Read(MRR)优化
。Multi-Range Read优化的目的就是为了减少磁盘的随机访问
,并且将随机访问转化为较为顺序的数据访问,这对于IO-bound类型的SQL查询语句可带来性能极大的提升。Multi-Range Read优化可适用于range,ref,eq_ref类型的查询。
MRR优化有以下几个好处:
- MRR使数据访问变得较为顺序。在查询辅助索引时,首先根据得到的查询结果,按照主键进行排序,并按照主键排序的顺序进行书签查找。
- 减少缓冲池中页被替换的次数。
- 批量处理对键值的查询操作。
对于InnoDB和MyISAM存储引擎的范围查询和JOIN查询操作,MRR的工作方式如下:
- 将查询得到的辅助索引键值存放于一个缓存中,这时缓存中的数据是根据辅助索引键值排序的。
- 将缓存中的键值根据RowID进行排序。
- 根据RowID的排序顺序来访问实际的数据文件。
SELECT*FROM salaries WHERE salary>10000 AND salary<40000; salary上有一个辅助索引idx_s,因此除了通过辅助索引查找键值外,还需要通过书签查找来进行对整行数据的查询。当不启用Multi-Range Read特性时,看到的执行计划如图
若启用Mulit-Range Read特性,则除了会在列Extra看到Using index condition外,还会看见Using MRR选项,如图
是否启用Multi-Range Read优化可以通过参数optimizer_switch中的标记(flag)来控制。当mrr为on时,表示启用Multi-Range Read优化。mrr_cost_based标记表示是否通过cost based的方式来选择是否启用mrr。若将mrr设为on,mrr_cost_based设为off,则总是启用Multi-Range Read优化。例如,下述语句可以将Multi-Range Read优化总是设为开启状态: mysql>SET@@optimizer_switch=‘mrr=on,mrr_cost_based=off’;
Index Condition Pushdown(ICP)优化
和Multi-Range Read一样,Index Condition Pushdown同样是MySQL 5.6开始支持的一种根据索引进行查询的优化方式。之前的MySQL数据库版本不支持Index Condition Pushdown,当进行索引查询时,首先根据索引来查找记录,然后再根据WHERE条件来过滤记录。在支持Index Condition Pushdown后,MySQL数据库会在取出索引的同时,判断是否可以进行WHERE条件的过滤,也就是将WHERE的部分过滤操作放在了存储引擎层
。在某些查询下,可以大大减少上层SQL层对记录的索取(fetch),从而提高数据库的整体性能。
Index Condition Pushdown优化支持range、ref、eq_ref、ref_or_null类型的查询,当前支持MyISAM和InnoDB存储引擎。当优化器选择Index Condition Pushdown优化时,可在执行计划的列Extra看到Using index condition提示。
假设某张表有联合索引(zip_code,last_name,firset_name),并且查询语句如下:
SELECT*FROM people
WHERE zipcode='95054'
AND lastname LIKE'%etrunia%'
AND address LIKE'%Main Street%';
对于上述语句,MySQL数据库可以通过索引来定位zipcode等于95 054的记录,但是索引对WHERE条件的lastname LIKE’%etrunia%‘AND address LIKE’%Main Street%'没有任何帮助。若不支持Index Condition Pushdown优化,则数据库需要先通过索引取出所有zipcode等于95 054的记录,然后再过滤WHERE之后的两个条件。
若支持Index Condition Pushdown优化,则在索引取出时,就会进行WHERE条件的过滤,然后再去获取记录。这将极大地提高查询的效率。
InnoDB存储引擎中的哈希算法
哈希算法是一种常见算法,时间复杂度为O(1)
,且不只存在于索引中,每个数据库应用中都存在该数据库结构。设想一个问题,当前服务器的内存为128GB时,用户怎么从内存中得到某一个被缓存的页呢?虽然内存中查询速度很快,但是也不可能每次都要遍历所有
内存来进行查找,这时对于字典操作
只需O(1)的哈希算法就有了很好的用武之地。
InnoDB存储引擎使用哈希算法
来对字典
进行查找,其冲突机制采用链表方式
,哈希函数采用除法散列
方式。对于缓冲池页的哈希表来说,在缓冲池中的Page页
都有一个chain指针
,它指向相同哈希函数值的页。而对于除法散列,m的取值为略大于2倍的缓冲池页数量的质数。例如:当前参数innodb_buffer_pool_size
的大小为10M,则共有640个16KB的页。对于缓冲池页内存的哈希表来说,需要分配640×2=1280个槽,但是由于1280不是质数,需要取比1280略大的一个质数,应该是1399,所以在启动时会分配1399个槽的哈希表,用来哈希查询所在缓冲池中的页。
InnoDB存储引擎的表空间都有一个space_id,用户所要查询的应该是某个表空间的某个连续16KB的页,即偏移量offset。InnoDB存储引擎将space_id左移20位,然后加上这个space_id和offset,即关键字K=space_id<<20+space_id+offset,
然后通过除法散列 k % m(1399)
到各个槽中去。
自适应哈希索引采用哈希表的方式实现。不同的是,这仅是数据库自身创建并使用的,DBA本身并不能对其进行干预。自适应哈希索引经哈希函数映射到一个哈希表中,因此对于字典类型的查找非常快速,如SELECT*FROM TABLE WHERE index_col=‘xxx’。但是对于范围查找就无能为力了。
全文检索
**全文检索(Full-Text Search)是将存储于数据库中的所有的整本书或整篇文章中的任意内容信息查找出来的技术。**它可以根据需要获得全文中有关章、节、段、句、词等信息,也可以进行各种统计和分析。从InnoDB 1.2.x版本开始,InnoDB存储引擎开始支持全文检索。
全文检索通常使用倒排索引(inverted index)来实现
。倒排索引同B+树索引一样,也是一种索引结构。它在辅助表(auxiliary table)
中存储了单词与单词自身在一个或多个文档中所在位置之间的映射。这通常利用关联数组实现,其拥有两种表现形式:
- inverted file index,其表现形式为单词,单词所在文档的ID
full inverted index,其表现形式为单词,(单词所在文档的ID,在具体文档中的位置)
例如,对于下面这个例子,表t存储的内容如表
对于inverted file index 和 full invertedindex的关联数组,其存储的内容如表
InnoDB存储引擎从1.2.x版本开始支持全文检索的技术,其采用full inverted index的方式。在InnoDB存储引擎中,将(DocumentId,Position)视为一个“ilist”。因此在全文检索的表中,有两个列,一个是word字段,另一个是ilist字段,并且在word字段上有设有索引。此外,由于InnoDB存储引擎在ilist字段中存放了Position信息,故可以进行Proximity Search,而MyISAM存储引擎不支持该特性。
正如之前所说的那样,倒排索引需要将word存放到一张表中,这个表称为Auxiliary Table(辅助表)。在InnoDB存储引擎中,为了提高全文检索的并行性能,共有6张Auxiliary Table,目前每张表根据word的Latin编码进行分区。Auxiliary Table是持久的表,存放于磁盘上。然而在InnoDB存储引擎的全文索引中,还有另外一个重要的概念FTS Index Cache(全文检索索引缓存),其用来提高全文检索的性能。
FTS Index Cache是一个红黑树结构,其根据(word,ilist)进行排序。这意味着插入的数据已经更新了对应的表,但是对全文索引的更新可能在分词操作后还在FTS Index Cache中,Auxiliary Table可能还没有更新。InnoDB存储引擎会批量对Auxiliary Table进行更新,而不是每次插入后更新一次Auxiliary Table。当对全文检索进行查询时,Auxiliary Table首先会将在FTS Index Cache中对应的word字段合并到Auxiliary Table中,然后再进行查询。这种merge操作非常类似之前介绍的Insert Buffer的功能,不同的是Insert Buffer是一个持久的对象,并且其是B+树的结构。然而FTS Index Cache的作用又和Insert Buffer是类似的,它提高了InnoDB存储引擎的性能,并且由于其根据红黑树排序后进行批量插入,其产生的Auxiliary Table相对较小。Auxiliary Table中,然后再进行查询。这种merge操作非常类似之前介绍的Insert Buffer是类似的,它提高了InnoDB存储引擎的性能,并且由于其根据红黑树排序后进行批量插入,其产生的Auxiliary Table相对较小。
参数innodb_ft_cache_size用来控制FTS Index Cache的大小,默认值为32M。当该缓存满时,会将其中的(word,ilist)分词信息同步到磁盘的Auxiliary Table中。增大该参数可以提高全文检索的性能,但是在宕机时,未同步到磁盘中的索引信息可能需要更长的时间进行恢复。
MySQL数据库支持全文检索(Full-Text Search)的查询,其语法为:
MATCH(col1,col2,…)AGAINST(expr[search_modifier])
search_modifier:
IN NATURAL LANGUAGE MODE
|IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
|IN BOOLEAN MODE
|WITH QUERY EXPANSION
MySQL数据库通过MATCH()…AGAINST()语法支持全文检索的查询,MATCH指定了需要被查询的列,AGAINST指定了使用何种方法去进行查询。
以上是关于MySql记录的一些使用方法和经验的主要内容,如果未能解决你的问题,请参考以下文章