热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mysql死锁分析_【mysql】MySQL知识整理死锁分析性能优化等

[[TOC]]常用操作指令showdatabases:显示所有的数据库;usedbName:使用指定数据库showtables:显示所有的数据表

[[TOC]]

常用操作指令

show databases:显示所有的数据库;

use dbName: 使用指定数据库

show tables: 显示所有的数据表;

desc tableName: 查看数据表的字段信息;

show create table tableName: 查询创建表的所有信息;

show create database dbName: 查看数据库创建指令;

show full processlist: 查看所有进程

drop table tableName: 删除表

alter table tableName add constraint 主键(如:PK_TableName) primary key tableName(主键字段):添加主键约束

alter table tableName add constraint 从表 (如:FK_从表_主表) foreign key 从表(外键字段) references 主表(主键字段): 添加外键约束

alter table tableName add constraint 唯一约束 (如:uk_t_1) unique(字段名): 添加唯一约束;

alter table tableName drop primary key: 删除主键约束

alter table tableName drop foreign key 外键(区分大小写): 删除外键约束

alter table tableName add index value_domain_idx(domain_id, value): 添加索引value_domain_idx

alter table tableName drop index pool_domain_idx: 删除索引 pool_domain_idx

show index from table: 显示表的所有索引;

mysqldump -uroot -pXXXX -h19.168.5.2 -P30118 --databases mgmt >/tmp/mgmt.sql: 导出指定数据库

Demo

查看变量(两种方式)

// 查看事务隔离级别: 方式1

MySQL [(none)]> show variables like "%iso%";

+---------------+-----------------+

| Variable_name | Value |

+---------------+-----------------+

| tx_isolation | REPEATABLE-READ |

+---------------+-----------------+

1 row in set (0.00 sec)

// 方式2

MySQL [(none)]> select @tx_isolation;

+---------------+

| @tx_isolation |

+---------------+

| NULL |

+---------------+

1 row in set (0.00 sec)

// 查看最大连接数: 方式1

MySQL [(none)]> show variables like "%max_conn%";

+--------------------+-------+

| Variable_name | Value |

+--------------------+-------+

| max_connect_errors | 100 |

| max_connections | 2000 |

+--------------------+-------+

2 rows in set (0.00 sec)

// 方式2:

MySQL [(none)]> select @@max_connections;

+-------------------+

| @@max_connections |

+-------------------+

| 2000 |

+-------------------+

1 row in set (0.00 sec)

设置变量的值

MySQL [(none)]> select @@max_connections;

+-------------------+

| @@max_connections |

+-------------------+

| 3000 |

+-------------------+

1 row in set (0.00 sec)

MySQL [(none)]> set global max_connections=4000;

Query OK, 0 rows affected (0.00 sec)

MySQL [(none)]> select @@max_connections;

+-------------------+

| @@max_connections |

+-------------------+

| 4000 |

+-------------------+

1 row in set (0.00 sec)

创建数据库

create database if not exists `myTestDB`

创建数据表

create table if not exists `t_user`(

`userid` int(11) not null auto_increment,

`userName` varchar(32) not null DEFAULT '',

`password` varchar(32) DEFAULT null,

`createTime` timestamp not null DEFAULT CURRENT_TIMESTAMP,

`status` smallint(4) default null,

`lastLoginTime` datetime DEFAULT null,

primary key (`userid`),

UNIQUE key `userName`(`userName`)

)ENGINE=InnoDB auto_increment=3 default CHARSET=utf8;

插入数据

在指定的列中插入数据

insert into t_user(userName,password,createTime,status,lastLoginTime) values("Tom","12345","2016-12-12 13:45:12",1,"2016-12-12 13:45:12");

insert into t_user(userName,password,createTime,status,lastLoginTime) values("Lily","12345","2016-12-12 14:45:12",1,"2016-12-12 14:45:12");

insert into t_user(userName,password,status,lastLoginTime) values("Jenny","12345",1,"2016-12-12 14:45:12");

性能优化

索引的设计

Innodb表尽量使用自己指定的主键

Innodb表,主键使用聚合索引,聚合索引会保存完整记录的值,即:数据文件本身就是索引文件,同时数据文件还是一个BTREE结构;

Innodb表的主键索引--聚合索引

936b1b54c25da59c1e25c1731e873a58.png

Innodb的主键应该尽可能的 短

Innodb表中,普通索引都会保存主键的键值,所以主键长度越短越好

Innodb表的普通索引: 叶子节点会保存主键的值

df7bb6aa39657af046035da907cadc50.png

问题:为什么选择保存主键值,而不是保存记录的物理地址?

这样的策略减少了当出现行移动或者数据分页时二级索引的维护工作;

二级索引会占用更多的空间,换来的好处是,Innodb在移动行时,无需更新二级索引中的“指针”;

即:以空间换取二级索引的维护工作;

使用唯一索引

开启profiles

查看是否开启:默认时没有开启

MySQL [test]> show variables like "%profi%";

+------------------------+-------+

| Variable_name | Value |

+------------------------+-------+

| have_profiling | YES |

| profiling | OFF|

| profiling_history_size | 15 |

+------------------------+-------+

开启:

set profiling=1;

MySQL [test]> show variables like "%profi%";

+------------------------+-------+

| Variable_name | Value |

+------------------------+-------+

| have_profiling | YES |

| profiling | ON |

| profiling_history_size | 15 |

+------------------------+-------+

显示查询性能:

MySQL [test]> show profiles;

+----------+------------+----------------------------------------------------------------------------------+

| Query_ID | Duration | Query |

+----------+------------+----------------------------------------------------------------------------------+

| 1 | 0.00077150 | show variables like "%profi%" |

| 2 | 0.00098675 | select * from pool_configs where pool_id like "7b8f0f5e2fbb4d9aa2d5fd55466dsij%" |

+----------+------------+----------------------------------------------------------------------------------+

2 rows in set, 1 warning (0.00 sec)

索引的选择性

另一种不建议建索引的情况是索引的选择性较低。所谓索引的选择性(Selectivity),是指不重复的索引值(也叫基数,Cardinality)与表记录数(#T)的比值:

Index Selectivity = Cardinality / #T

显然选择性的取值范围为(0, 1],选择性越高的索引价值越大,这是由B+Tree的性质决定的。

使用示例:

CREATE TABLE `pool_configs` (

`id` char(32) NOT NULL,

`pool_id` char(32) NOT NULL,

`region_name` varchar(50) DEFAULT NULL,

`domain_id` char(32) DEFAULT NULL,

`value` varchar(50) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `pool_id_index` (`pool_id`),

KEY `domain_index` (`domain_id`),

KEY `pool_domain_value_idx` (`pool_id`,`domain_id`,`value`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

上面的索引pool_domain_value_idx由3列组成:pool_id,domain_id,value;

则该索引的选择性:

MySQL [test]> select count(distinct(concat(pool_id,domain_id,value)))/count(*) as selectivity from pool_configs;

+-------------+

| selectivity |

+-------------+

| 0.2254 |

+-------------+

索引的选择性 与 前缀索引 组合

假设有两列:pool_id, domain_id,长度都为32;

CREATE TABLE `pool_configs` (

`id` char(32) NOT NULL,

`pool_id` char(32) NOT NULL,

`region_name` varchar(50) DEFAULT NULL,

`domain_id` char(32) DEFAULT NULL,

`value` varchar(50) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

计算如下两个选择性:

pool_id+domain_id组合:总共64位;

pool_id+domain_id(前8)组合:总共40位;

MySQL [test]> select count(distinct(concat(pool_id, domain_id)))/count(*) as selectivity from pool_configs;

+-------------+

| selectivity |

+-------------+

| 0.9127 |

+-------------+

1 row in set (0.00 sec)

MySQL [test]> select count(distinct(concat(pool_id, left(domain_id,8))))/count(*) as selectivity from pool_configs;

+-------------+

| selectivity |

+-------------+

| 0.8563 |

+-------------+

从上面可以发现,使用组合2可以节省将近一半的索引长度,但是选择性并没有降低多少;

那在建立索引的时候,就可以这样进行建立:

alter table pool_configs add index poolId_domainId8_idx(pool_id, domain_id(8)); // 只使用前8位

CREATE TABLE `pool_configs` (

`id` char(32) NOT NULL,

`pool_id` char(32) NOT NULL,

`region_name` varchar(50) DEFAULT NULL,

`domain_id` char(32) DEFAULT NULL,

`value` varchar(50) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `poolId_domainId8_idx` (`pool_

这种方式,既满足了选择性较高,且索引长度较短,此种建立索引的方式就是前缀索引:只使用最左前缀的部分列长度;

前缀索引的局限性

前缀索引不能用于ORDER BY和GROUP BY操作,也不能用于Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)

查看索引使用情况

Handler_read_key: 代表行被索引读取的次数,越高越好,很低表名索引没怎么起作用;

Handler_read_rnd_next: 高,通常表名索引使用不争取,或没有使用索引;

MySQL [test]> show status like "handler_read%";

+-----------------------+-------+

| Variable_name | Value |

+-----------------------+-------+

| Handler_read_first | 12 |

| Handler_read_key | 12 |

| Handler_read_last | 0 |

| Handler_read_next | 6 |

| Handler_read_prev | 0 |

| Handler_read_rnd | 0 |

| Handler_read_rnd_next | 644 |

+-----------------------+-------+

死锁排查相关指令

查看事务隔离级别

mysql> select @@tx_isolation;

+-----------------+

| @@tx_isolation |

+-----------------+

| REPEATABLE-READ |

+-----------------+

1 row in set

设置打印死锁日志

set global innodb_print_all_deadlocks = 1;

查看最近一次死锁

show engine innodb status;

然后在打印的日志中,定位到:LATEST DETECTED DEADLOCK

示例

遇到死锁,第一步就是阅读死锁日志。

死锁日志通常分为两部分:

上半部分说明事务1在等待什么锁;

下半部分说明事务2当前只有的锁以及等待的锁;

死锁日志的术语:

S锁:共享锁;

X锁:排它锁;

RECORD LOCKS:记录锁(行锁);

------------------------

LATEST DETECTED DEADLOCK

------------------------

2018-01-05 07:42:47 7f97a6aaf700

*** (1) TRANSACTION:

TRANSACTION 633399987, ACTIVE 21 sec starting index read

//## 事务活跃了21秒,当前状态为读索引

mysql tables in use 1, locked 1

//## 有一个table被使用,表上有一个表锁

LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)

//## 当前事务持有1个行锁

MySQL thread id 83758029, OS thread handle 0x7f97a8823700, query id 1497915714 172.30.29.0 root updating

delete from test where a=2 //###当前事务正在执行该语句

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 3441 page no 4 n bits 72 index `a` of table `test`.`test` trx id 633399987 lock_mode X waiting

//### 事务1正在申请索引a的X锁(排它锁)

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32

0: len 4; hex 00000002; asc ;;

1: len 4; hex 00000002; asc ;;

*** (2) TRANSACTION:

TRANSACTION 633399683, ACTIVE 55 sec inserting

mysql tables in use 1, locked 1

4 lock struct(s), heap size 1184, 3 row lock(s), undo log entries 2

MySQL thread id 83757528, OS thread handle 0x7f97a6aaf700, query id 1497916206 172.30.29.0 root update

insert into test (id, a) values (10, 2)

*** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 3441 page no 4 n bits 72 index `a` of table `test`.`test` trx id 633399683 lock_mode X locks rec but not gap

//### 事务2持有X锁,并且是记录锁

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32

0: len 4; hex 00000002; asc ;;

1: len 4; hex 00000002; asc ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 3441 page no 4 n bits 72 index `a` of table `test`.`test` trx id 633399683 lock mode S waiting

//### 事务2正在申请索引a的S锁(共享锁),因为事务1提前申请了该锁,所以造成了死锁

Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 32

0: len 4; hex 00000002; asc ;;

1: len 4; hex 00000002; asc ;;

*** WE ROLL BACK TRANSACTION (1)

InnoDB目前处理死锁的方法

InnoDB目前处理死锁的方法是将持有最少行级排他锁的事务进行回滚。

Sql慢查询日志

TODO

Mysql优秀博文-好文

深入浅出的讲解了数据库死锁原理;

讲解索引的好文章

Innodb和myisam索引实现原理:B+TREE索引、聚合索引、非聚合索引;

最左前缀原理与相关优化



推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • 本文介绍了如何使用PHP代码将表格导出为UTF8格式的Excel文件。首先,需要连接到数据库并获取表格的列名。然后,设置文件名和文件指针,并将内容写入文件。最后,设置响应头部,将文件作为附件下载。 ... [详细]
  • 本文提供了关于数据库设计的建议和注意事项,包括字段类型选择、命名规则、日期的加入、索引的使用、主键的选择、NULL处理、网络带宽消耗的减少、事务粒度的控制等方面的建议。同时还介绍了使用Window Functions进行数据处理的方法。通过遵循这些建议,可以提高数据库的性能和可维护性。 ... [详细]
  • 常用工具(一)
    1.时间戳在线转换工具(1)链接https:tool.lutimestamp(2)说明可以通过此工具:将时间戳转为具体时间点,也可以将具体时间点转为时间戳(3)效果2.JSON在线 ... [详细]
author-avatar
财珍文纶1
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有