龙空技术网

mysql information_schema元数据和索引介绍

孫攀龍 166

前言:

现在朋友们对“mysql decimal62是什么意思”都比较珍视,各位老铁们都想要分析一些“mysql decimal62是什么意思”的相关知识。那么小编也在网络上网罗了一些对于“mysql decimal62是什么意思””的相关文章,希望我们能喜欢,你们一起来了解一下吧!

information_schema.tables

information_schema.tables

元数据?

----> “基表”(无法直接查询和修改的)

----> DDL 进行元数据修改

----> show ,desc(show),information_schema(全局类的统计和查询)

use information_schema

desc tables;

TABLE_SCHEMA 表所在的库

TABLE_NAME 表名

ENGINE 表的存储引擎

TABLE_ROWS 表的行数

AVG_ROW_LENGTH 平均行长度

INDEX_LENGTH 索引的长度

-- information_schema

--- 查询整个数据库中所有的库对应的表名

例如:

world city

world country

oldboy oldguo

SELECT table_schema,table_name

FROM information_schema.tables;

information_schema INNODB_SYS_FOREIGN

information_schema INNODB_SYS_TABLESTATS

liexin_crmv2 lie_approve_result

liexin_crmv2 lie_change_record

liexin_crmv2 lie_company

liexin_crmv2 lie_company_terminal_info

liexin_crmv2 lie_invoice_approve

liexin_crmv2 lie_task

liexin_crmv2 lie_user

liexin_crmv2 lie_user_feedback

--- 查询world和school库下的所有表名

SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema='world' UNION ALL SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema='school';

--- 查询整个数据库中所有的库对应的表名,每个库显示成一行

SELECT table_schema,GROUP_CONCAT(table_name)

FROM information_schema.tables

GROUP BY table_schema;

--- 统计一下每个库下的表的个数

SELECT table_schema,COUNT(table_name)

FROM information_schema.tables

GROUP BY table_schema;

--- 统计一下每个库的真实数据量

每张表数据量=AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH

SELECT

SUM(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024/1024 AS total_mb

FROM information_schema.TABLES

--- information_schema.tables+CONCAT(),拼接命令

--- 使用方法举例

mysql> SELECT CONCAT(USER,"@","'",HOST,"'") FROM mysql.user;

--- 生产需求1

mysqldump -uroot -p123 world city >/tmp/world_city.sql

--- 模仿以上命令,对整个数据库下的1000张表进行单独备份,

--- 排除sys,performance,information_schema

mysqldump -uroot -p123 world city >/tmp/world_city.sql

SELECT CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name," >/tmp/",table_schema,"_",table_name,".sql")

FROM information_schema.tables

WHERE table_schema NOT IN('sys','performance','information_schema')

INTO OUTFILE '/tmp/bak.sh';

vim /etc/my.cnf

secure-file-priv=/tmp

/etc/init.d/mysqld restart

--- 例子:模仿以下语句,批量实现world下所有表的操作语句生成

alter table world.city discard tablespace;

select concat("alter table ",table_schema,".",table_name,"discard tablespace;")

from information_schema.tables

where table_schema='world'

into outfile '/tmp/discard.sql';

5. show

show databases; 查看所有数据库名

show tables; 查看当前库下的表名

show tables from world; 查看world数据库下的表名

show create database 查看建库语句

show create table 查看建表语句

show grants for root@'localhost' 查看用户权限信息

show charset 查看所有的字符集

show collation 查看校对规则

show full processlist 查看数据库连接情况

show status 查看数据库的整体状态

show status like '%lock%' 模糊查看数据库的整体状态

show variables 查看数据库所有变量情况

show variables like '%innodb%' 查看数据库所有变量情况

show engines 查看所有支持存储引擎

show engine innodb status 查看所有innodb存储引擎状态情况

show binary logs 查看二进制日志情况

show binlog events in 查看二进制日志事件

show relaylog events in 查看relay日志事件

show slave status 查看从库状态

show master status 查看数据库binlog位置信息

show index from 查看表的索引情况

6. 索引

创建100万数据

create table t100w (id int,num int,k1 char(2),k2 char(4),dt timestamp);delimiter //create  procedure rand_data(in num int)begindeclare str char(62) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';declare str2 char(2);declare str4 char(4);declare i int default 0;while i<num doset str2=concat(substring(str,1+floor(rand()*61),1),substring(str,1+floor(rand()*61),1));set str4=concat(substring(str,1+floor(rand()*61),2),substring(str,1+floor(rand()*61),2));set i=i+1;insert into t100w values (i,floor(rand()*num),str2,str4,now());end while;end;//delimiter ;插入100w条数据:call rand_data(1000000);commit;
1. 索引作用
提供了类似于书中目录的作用,目的是为了优化查询
索引的种类(算法)
B树索引Hash索引R树Full textGIS 
3. B树 基于不同的查找算法分类介绍
B-treeB+Tree 在范围查询方面提供了更好的性能(> < >= <= like)B*Tree
在功能上的分类4.1 辅助索引(S)怎么构建B树结构的?
(1). 索引是基于表中,列(索引键)的值生成的B树结构(2). 首先提取此列所有的值,进行自动排序(3). 将排好序的值,均匀的分布到索引树的叶子节点中(16K)(4). 然后生成此索引键值所对应得后端数据页的指针(5). 生成枝节点和根节点,根据数据量级和索引键长度,生成合适的索引树高度id  name  age  genderselect  *  from  t1 where id=10;问题: 基于索引键做where查询,对于id列是顺序IO,但是对于其他列的查询,可能是随机IO.
4.2 聚集索引(C)4.2.1 前提
(1)表中设置了主键,主键列就会自动被作为聚集索引.(2)如果没有主键,会选择唯一键作为聚集索引.(3)聚集索引必须在建表时才有意义,一般是表的无关列(ID)
4.2.2 辅助索引(S)怎么构建B树结构的?
(1) 在建表时,设置了主键列(ID)(2) 在将来录入数据时,就会按照ID列的顺序存储到磁盘上.(我们又称之为聚集索引组织表)(3) 将排好序的整行数据,生成叶子节点.可以理解为,磁盘的数据页就是叶子节点
4.2.3 聚集索引和辅助索引构成区别
聚集索引只能有一个,非空唯一,一般时主键辅助索引,可以有多个,时配合聚集索引使用的聚集索引叶子节点,就是磁盘的数据行存储的数据页MySQL是根据聚集索引,组织存储数据,数据存储时就是按照聚集索引的顺序进行存储数据辅助索引,只会提取索引键值,进行自动排序生成B树结构
5.辅助索引细分
1.普通的单列辅助索引2.联合索引多个列作为索引条件,生成索引树,理论上设计的好的,可以减少大量的回表查询3.唯一索引索引列的值都是唯一的.
6. 关于索引树的高度受什么影响
1. 数据量级, 解决方法:分表,分库,分布式2. 索引列值过长 , 解决方法:前缀索引3. 数据类型:变长长度字符串,使用了char,解决方案:变长字符串使用varcharenum类型的使用enum ('山东','河北','黑龙江','吉林','辽宁','陕西'......)                                         1      2      3
7. 索引的基本管理7.1 索引建立前
db01 [world]>desc city;+-------------+----------+------+-----+---------+----------------+| Field      | Type    | Null | Key | Default | Extra          |+-------------+----------+------+-----+---------+----------------+| ID          | int(11)  | NO  | PRI | NULL    | auto_increment || Name        | char(35) | NO  |    |        |                || CountryCode | char(3)  | NO  | MUL |        |                || District    | char(20) | NO  |    |        |                || Population  | int(11)  | NO  |    | 0      |                |+-------------+----------+------+-----+---------+----------------+5 rows in set (0.00 sec)Field :列名字key  :有没有索引,索引类型PRI: 主键索引UNI: 唯一索引MUL: 辅助索引(单列,联和,前缀)
7.1 单列普通辅助索引7.1.1 创建索引
db01 [world]>alter table city add index idx_name(name);                                       表                    索引名(列名)db01 [world]>create index idx_name1 on city(name);db01 [world]>show index from city;![image]()注意:以上操作不代表生产操作,我们不建议在一个列上建多个索引同一个表中,索引名不能同名。### 7.1.2 删除索引:db01 [world]>alter table city drop index idx_name1;                                        表名                 索引名
7.2 覆盖索引(联合索引)
Master [world]>alter table city add index idx_co_po(countrycode,population);
7.3 前缀索引
db01 [world]>alter table city add index idx_di(district(5));注意:数字列不能用作前缀索引。
7.4 唯一索引
db01 [world]>alter table city add unique index idx_uni1(name);ERROR 1062 (23000): Duplicate entry 'San Jose' for key 'idx_uni1'

计city表中,以省的名字为分组,统计组的个数

select district,count(id) from city group by district;需求: 找到world下,city表中 name列有重复值的行,最后删掉重复的行db01 [world]>select name,count(id) as cid from city group by name  having cid>1 order by cid desc;db01 [world]>select * from city where name='suzhou';
8. 执行计划获取及分析8.0 介绍

(1) 获取到的是优化器选择完成的,他认为代价最小的执行计划. 作用: 语句执行前,先看执行计划信息,可以有效的防止性能较差的语句带来的性能问题. 如果业务中出现了慢语句,我们也需要借助此命令进行语句的评估,分析优化方案。 (2) select 获取数据的方法 1. 全表扫描(应当尽量避免,因为性能低) 2. 索引扫描 3. 获取不到数据

8.2 执行计划分析8.2.0 重点关注的信息

table: city                              ---->查询操作的表    **possible_keys: CountryCode,idx_co_po      ---->可能会走的索引  **key: CountryCode   ---->真正走的索引    ***type: ref   ---->索引类型        *****Extra: Using index condition              ---->额外信息        *****
8.2.1 type详解
从左到右性能依次变好.ALL  :  全表扫描,不走索引例子:1. 查询条件列,没有索引SELECT * FROM t_100w WHERE k2='780P';  2. 查询条件出现以下语句(辅助索引列)USE world DESC city;DESC SELECT * FROM city WHERE countrycode <> 'CHN';DESC SELECT * FROM city WHERE countrycode NOT IN ('CHN','USA');DESC SELECT * FROM city WHERE countrycode LIKE '%CH%';注意:对于聚集索引列,使用以上语句,依然会走索引DESC SELECT * FROM city WHERE id <> 10;INDEX  :全索引扫描1. 查询需要获取整个索引树种的值时:DESC  SELECT countrycode  FROM city;2. 联合索引中,任何一个非最左列作为查询条件时:idx_a_b_c(a,b,c)  ---> a  ab  abcSELECT * FROM t1 WHERE b SELECT * FROM t1 WHERE c    RANGE :索引范围扫描 辅助索引> < >= <= LIKE IN OR 主键 <>  NOT IN例子:1. DESC SELECT * FROM city WHERE id<5;2. DESC SELECT * FROM city WHERE countrycode LIKE 'CH%';3. DESC SELECT * FROM city WHERE countrycode IN ('CHN','USA');注意: 1和2例子中,可以享受到B+树的优势,但是3例子中是不能享受的.所以,我们可以将3号列子改写:DESC SELECT * FROM city WHERE countrycode='CHN'UNION ALL SELECT * FROM city WHERE countrycode='USA';ref: 非唯一性索引,等值查询DESC SELECT * FROM city WHERE countrycode='CHN';eq_ref: 在多表连接时,连接条件使用了唯一索引(uk  pK)DESC SELECT b.name,a.name FROM city AS a JOIN country AS b ON a.countrycode=b.code WHERE a.population <100;system,const :唯一索引的等值查询DESC SELECT * FROM city WHERE id=10;
8.2.2 其他字段解释Extra: NULL 额外的信息using filesort 文件排序 二次排序(危险 需要优化 - 联合索引)
filesort ,文件排序.SHOW INDEX FROM city;ALTER TABLE city ADD INDEX CountryCode(CountryCode);ALTER TABLE city DROP INDEX idx_c_p;DESC SELECT * FROM city WHERE countrycode='CHN'  ORDER BY population ALTER TABLE city ADD INDEX idx_(population);DESC SELECT * FROM city WHERE countrycode='CHN'  ORDER BY population ALTER TABLE city ADD INDEX idx_c_p(countrycode,population);ALTER TABLE city DROP INDEX idx_;ALTER TABLE city DROP INDEX CountryCode;DESC SELECT * FROM city WHERE countrycode='CHN'  ORDER BY population 结论: 1.当我们看到执行计划extra位置出现filesort,说明由文件排序出现2.观察需要排序(ORDER BY,GROUP BY ,DISTINCT )的条件,有没有索引3. 根据子句的执行顺序,去创建联合索引索引优化效果测试:优化前:[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf \> --concurrency=100 --iterations=1 --create-schema='oldboy' \> --query="select * from oldboy.t_100w where k2='780P'" engine=innodb \> --number-of-queries=2000 -uroot -p123 -verbosemysqlslap: [Warning] Using a password on the command line interface can be insecure.Benchmark    Running for engine rbose    Average number of seconds to run all queries: 701.743 seconds    Minimum number of seconds to run all queries: 701.743 seconds    Maximum number of seconds to run all queries: 701.743 seconds    Number of clients running queries: 100    Average number of queries per client: 20优化后:[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='oldboy' --query="select * from oldboy.t_100w where k2='780P'" engine=innodb --number-of-queries=2000 -uroot -p123 -verbosemysqlslap: [Warning] Using a password on the command line interface can be insecure.Benchmark    Running for engine rbose    Average number of seconds to run all queries: 0.190 seconds    Minimum number of seconds to run all queries: 0.190 seconds    Maximum number of seconds to run all queries: 0.190 seconds    Number of clients running queries: 100    Average number of queries per client: 20联合索引:1. SELECT * FROM t1  WHERE a=    b=   我们建立联合索引时:ALTER TABLE t1 ADD INDEX idx_a_b(a,b);  ALTER TABLE t1 ADD INDEX idx_b_a(b,a);  以上的查询不考虑索引的顺序,优化器会自动调整where的条件顺序注意: 索引,我们在这种情况下建索引时,需要考虑哪个列的唯一值更多,哪个放在索引左边.2.  如果出现where 条件中出现不等值查询条件DESC  SELECT * FROM t_100w WHERE num <1000 AND k2='DEEF';我们建索引时:ALTER TABLE t_100w ADD INDEX idx_2_n(k2,num);语句书写时DESC  SELECT * FROM t_100w WHERE  k2='DEEF'  AND  num <1000 ;3. 如果查询中出现多子句我们要按照子句的执行顺序进行建立索引.
8.2.3 explain(desc)使用场景(面试题)
题目意思:  我们公司业务慢,请你从数据库的角度分析原因1.mysql出现性能问题,我总结有两种情况:(1)应急性的慢:突然夯住应急情况:数据库hang(卡了,资源耗尽)处理过程:1.show processlist;  获取到导致数据库hang的语句2. explain 分析SQL的执行计划,有没有走索引,索引的类型情况3. 建索引,改语句(2)一段时间慢(持续性的):(1)记录慢日志slowlog,分析slowlog(2)explain 分析SQL的执行计划,有没有走索引,索引的类型情况(3)建索引,改语句
9. 索引应用规范
业务1.产品的功能2.用户的行为"热"查询语句 --->较慢--->slowlog"热"数据
9.1.2 选择唯一性索引
唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。例如,学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。如果使用姓名的话,可能存在同名现象,从而降低查询速度。优化方案:(1) 如果非得使用重复值较多的列作为查询条件(例如:男女),可以将表逻辑拆分(2) 可以将此列和其他的查询类,做联和索引select count(*) from world.city;select count(distinct countrycode) from world.city;select count(distinct countrycode,population ) from world.city;
9.1.3(必须的) 为经常需要where 、ORDER BY、GROUP BY,join on等操作的字段,
排序操作会浪费很多时间。where  A B C      ----》 A  B  Cin where A   group by B  order by CA,B,C如果为其建立索引,优化查询注:如果经常作为条件的列,重复值特别多,可以建立联合索引。
9.1.4 尽量使用前缀来索引

如果索引字段的值很长,最好使用值的前缀来索引。

9.1.5 限制索引的数目

索引的数目不是越多越好。 可能会产生的问题: (1) 每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。 (2) 修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。 (3) 优化器的负担会很重,有可能会影响到优化器的选择. percona-toolkit中有个工具,专门分析索引是否有用

9.1.6 删除不再使用或者很少使用的索引(percona toolkit)

pt-duplicate-key-checker 表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理 员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。

9.1.7 大表加索引,要在业务不繁忙期间操作9.1.8 尽量少在经常更新值的列上建索引9.1.9 建索引原则

(1) 必须要有主键,如果没有可以做为主键条件的列,创建无关列(2) 经常做为where条件列  order by  group by  join on, distinct 的条件(业务:产品功能+用户行为)(3) 最好使用唯一值多的列作为索引,如果索引列重复值较多,可以考虑使用联合索引(4) 列值长度较长的索引列,我们建议使用前缀索引.(5) 降低索引条目,一方面不要创建没用索引,不常使用的索引清理,percona toolkit(xxxxx)(6) 索引维护要避开业务繁忙期
9.2.1 没有查询条件,或者查询条件没有建立索引
select * from tab;       全表扫描。select  * from tab where 1=1;在业务数据库中,特别是数据量比较大的表。是没有全表扫描这种需求。1、对用户查看是非常痛苦的。2、对服务器来讲毁灭性的。(1)select * from tab;SQL改写成以下语句:select  * from  tab  order by  price  limit 10 ;    需要在price列上建立索引(2)select  * from  tab where name='zhangsan'          name列没有索引改:1、换成有索引的列作为查询条件2、将name列建立索引
9.2.2 查询结果集是原表中的大部分数据,应该是25%以上。
查询的结果集,超过了总数行数25%,优化器觉得就没有必要走索引了。假如:tab表 id,name    id:1-100w  ,id列有(辅助)索引select * from tab  where id>500000;如果业务允许,可以使用limit控制。怎么改写 ?结合业务判断,有没有更好的方式。如果没有更好的改写方案尽量不要在mysql存放这个数据了。放到redis里面。
9.2.3 索引本身失效,统计数据不真实
索引有自我维护的能力。对于表内容变化比较频繁的情况下,有可能会出现索引失效。一般是删除重建现象:有一条select语句平常查询时很快,突然有一天很慢,会是什么原因select?  --->索引失效,,统计数据不真实DML ?   --->锁冲突
9.2.4 查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)
例子:错误的例子:select * from test where id-1=9;正确的例子:select * from test where id=10;算术运算函数运算子查询
9.2.5 隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.
这样会导致索引失效. 错误的例子:mysql> alter table tab add index inx_tel(telnum);Query OK, 0 rows affected (0.03 sec)Records: 0  Duplicates: 0  Warnings: 0mysql>mysql> desc tab;+--------+-------------+------+-----+---------+-------+| Field  | Type        | Null | Key | Default | Extra |+--------+-------------+------+-----+---------+-------+| id    | int(11)    | YES  |    | NULL    |      || name  | varchar(20) | YES  |    | NULL    |      || telnum | varchar(20) | YES  | MUL | NULL    |      |+--------+-------------+------+-----+---------+-------+3 rows in set (0.01 sec)mysql> select * from tab where telnum='1333333';+------+------+---------+| id  | name | telnum  |+------+------+---------+|    1 | a    | 1333333 |+------+------+---------+1 row in set (0.00 sec)mysql> select * from tab where telnum=1333333;+------+------+---------+| id  | name | telnum  |+------+------+---------+|    1 | a    | 1333333 |+------+------+---------+1 row in set (0.00 sec)mysql> explain  select * from tab where telnum='1333333';+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+| id | select_type | table | type | possible_keys | key    | key_len | ref  | rows | Extra                |+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+|  1 | SIMPLE      | tab  | ref  | inx_tel      | inx_tel | 63      | const |    1 | Using index condition |+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+1 row in set (0.00 sec)mysql> explain  select * from tab where telnum=1333333;+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra      |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|  1 | SIMPLE      | tab  | ALL  | inx_tel      | NULL | NULL    | NULL |    2 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+1 row in set (0.00 sec)mysql> explain  select * from tab where telnum=1555555;+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra      |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|  1 | SIMPLE      | tab  | ALL  | inx_tel      | NULL | NULL    | NULL |    2 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+1 row in set (0.00 sec)mysql> explain  select * from tab where telnum='1555555';+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+| id | select_type | table | type | possible_keys | key    | key_len | ref  | rows | Extra                |+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+|  1 | SIMPLE      | tab  | ref  | inx_tel      | inx_tel | 63      | const |    1 | Using index condition |+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+1 row in set (0.00 sec)mysql>
9.2.6 <> ,not in 不走索引(辅助索引)
EXPLAIN  SELECT * FROM teltab WHERE telnum  <> '110';EXPLAIN  SELECT * FROM teltab WHERE telnum  NOT IN ('110','119');mysql> select * from tab where telnum <> '1555555';+------+------+---------+| id  | name | telnum  |+------+------+---------+|    1 | a    | 1333333 |+------+------+---------+1 row in set (0.00 sec)mysql> explain select * from tab where telnum <> '1555555';单独的>,<,in 有可能走,也有可能不走,和结果集有关,尽量结合业务添加limitor或in  尽量改成unionEXPLAIN  SELECT * FROM teltab WHERE telnum  IN ('110','119');改写成:EXPLAIN SELECT * FROM teltab WHERE telnum='110'UNION ALLSELECT * FROM teltab WHERE telnum='119'
9.2.7 like "%_" 百分号在最前面不走
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%'  走range索引扫描EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110'  不走索引%linux%类的搜索需求,可以使用elasticsearch+mongodb 专门做搜索服务的数据库产品

“锁”顾名思义就是锁定的意思。 “锁”的作用是什么? 在事务ACID过程中,“锁”和“隔离级别”一起来实现“I”隔离性和"C" 一致性 (redo也有参与). 悲观锁:行级锁定(行锁) 谁先操作某个数据行,就会持有<这行>的(X)锁. 乐观锁: 没有锁

扩展内容(自己扩展)

Next LOCK 下键锁

GAP LOCK 间隙锁

悲观锁:

乐观锁:

第一种:

select id from t where id > 9 and id < 12 order by id for update

访问顺序 :

1. id=9,gap [5-10]

2. 向右遍历 next-lock 10-15,发现10>9,停止扫描,但由于不是等值12,所有next-lock保持不变更gap

最终锁范围: [5-10],[10-15] ====》 [5-15]

第二种

select id from t where id > 9 and id < 12 order by id desc for update

由于order by desc 的存在,查询优化器为了避免再排一次序,会将查找顺序优化为先找id <12

所以访问顺序

1. id=12 ,gap[10-15]

2. 向左遍历,next-lock ,扫到5-10范围,发现10>9,继续向左,扫到0-5,发现5<9,停止扫描

但由于不是等值9,所有next-lock保持不变更gap

最终锁范围: [0-5],[5-10],[10-15] ===> [0-15]

隔离级别

影响到数据的读取,默认的级别是 RR模式. transaction_isolation 隔离级别(参数) 负责的是,MVCC,读一致性问题 RU : 读未提交,可脏读,一般部议叙出现 RC : 读已提交,可能出现幻读,可以防止脏读. RR : 可重复读,功能是防止"幻读"现象 ,利用的是undo的快照技术+GAP(间隙锁)+NextLock(下键锁) SR : 可串行化,可以防止死锁,但是并发事务性能较差 补充: 在RC级别下,可以减轻GAP+NextLock锁的问题,但是会出现幻读现象,一般在为了读一致性会在正常select后添加for update语句.但是,请记住执行完一定要commit

否则容易出现所等待比较严重. 例如: [world]>select * from city where id=999 for update; [world]>commit;

RR级别:解决了 不可重复读问题+幻读的现象

不可重复读问题是由 undo的快照技术来解决。

幻读现象是由:MVCC+GAP+next-lock

架构改造项目

项目背景: 2台 IBM X3650 32G ,原来主从关系,2年多没有主从了,"小问题"不断(锁,宕机后的安全) MySQL 5.1.77 默认存储引擎 MyISAM 数据量: 60G左右 ,每周全备,没有开二进制日志 架构方案: 1. 升级数据库版本到5.7.20 2. 更新所有业务表的存储引擎为InnoDB 3. 重新设计备份策略为热备份,每天全备,并备份日志 4. 重新构建主从 结果: 1.性能 2.安全方面 3.快速故障处理

InnoDB存储引擎核心特性-参数补充

--存储引擎相关

查看

show engines;show variables like 'default_storage_engine';select @@default_storage_engine;
如何指定和修改存储引擎
(1) 通过参数设置默认引擎(2) 建表的时候进行设置(3) alter table t1 engine=innodb;
如何指定和修改存储引擎
(1) 通过参数设置默认引擎(2) 建表的时候进行设置(3) alter table t1 engine=innodb;
共享表空间
innodb_data_file_path一般是在初始化数据之前就设置好例子:innodb_data_file_path=ibdata1:512M:ibdata2:512M:autoextend
独立表空间
show variables like 'innodb_file_per_table';
缓冲区池查询

select @@innodb_buffer_pool_size; show engine innodb status\G innodb_buffer_pool_size 一般建议最多是物理内存的 75-80%

innodb_flush_log_at_trx_commit (双一标准之一)

作用主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、1、2三个。

控制了redo buffer 刷写策略,是一个安全参数,是在5.6版本以上默认的参数

查询select @@innodb_flush_log_at_trx_commit; #innodb_flush_log_at_trx_commit=1 参数说明:

1,每次事物的提交都会引起日志文件写入、flush磁盘的操作,确保了事务的ACID;flush 到操作系统的文件系统缓存 fsync到物理磁盘

0,表示当事务提交时,不做日志写入操作,而是每秒钟将log buffer中的数据写入文件系统缓存并且秒fsync磁盘一次;

2,每次事务提交引起写入文件系统缓存,但每秒钟完成一次fsync磁盘操作。

控制了redo buffer 刷写策略,是一个安全参数,是在5.6版本以上默认的参数

参数功能

1:每次事务提交,都会立即刷下redo到磁盘(redo buffer --每次事务-->os buffer(操作系统缓存) --每次事务--写入磁盘)

0:表示当事务提交时,不立即做日志写入操作(redo buffer --每秒-->os buffer (操作系统缓存)--每秒--磁盘)

2:每次事务提交引起写入文件系统缓存(redo buffer --每事务-->os buffer(操作系统缓存) --每秒--磁盘)

Innodb_flush_method=(O_DIRECT, fdatasync)

作用:

控制了 redo buffer 和 data bufffer 刷写磁盘方式

控制的是,log buffer 和data buffer,刷写磁盘的时候是否经过文件系统缓存

show variables like '%innodb_flush%';

O_DIRECT :数据缓冲区写磁盘,不走OS buffer(操作系统缓存)

fsync :日志和数据缓冲区写磁盘,都走OS buffer(操作系统缓存)

O_DSYNC :日志缓冲区写磁盘,不走 OS buffer(操作系统缓存)

最大安全模式:

innodb_flush_log_at_trx_commit=1

innodb_flush_method=O_DIRECT

最大性能模式:

innodb_flush_log_at_trx_commit=0

innodb_flush_method=fsync

## 4.3 关于redo设置

innodb_log_buffer_size= 128M 业务系统CPU压力有关

innodb_log_file_size=256 一般是1-2倍

innodb_log_files_in_group = 3 3-4组

redo日志有关的参数

innodb_log_buffer_size=16777216 内存大小innodb_log_file_size=50331648  文件大小innodb_log_files_in_group = 3
扩展(自己扩展,建议是官方文档。)
RR模式(对索引进行删除时):GAP:          间隙锁next-lock:    下一键锁定例子:id(有索引)1 2 3 4 5 6 GAP:在对3这个值做变更时,会产生两种锁,一种是本行的行级锁,另一种会在2和4索引键上进行枷锁next-lock:对第六行变更时,一种是本行的行级锁,在索引末尾键进行加锁,6以后的值在这时是不能被插入的。总之:GAP、next lock都是为了保证RR模式下,不会出现幻读,降低隔离级别或取消索引,这两种锁都不会产生。IX IS X S是什么?

相关文献:

Mysql 索引精讲

MySQL聚集索引和非聚集索引

B-/B+ 树看 MySQL索引实现,深入思考两个面试题背后的设计思路

为什么Mysql用B+树做索引,不用B-树或平衡二叉树?

MySQL死锁系列-常见加锁场景分析

mysql 锁机制详解加锁处理分析

mysql之innodb引擎的共享表空间和独立表空间

为什么MongoDB使用B-Tree,Mysql使用B+Tree

MySQL数据库 锁机制简介

Mysql并发时经典常见的死锁原因及解决方法

MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)

深入理解乐观锁与悲观锁

深入浅出mysql事务处理和锁机制

本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:

标签: #mysql decimal62是什么意思