MySql数据库出现死锁的情况(一)

在临近上线之前,我们系统做了一次压力测试,发现有一个接口在高并发情况下会出现一个死锁的情况。。首先申明…不是我写的,我只是帮忙排查下。

随着对Mysql锁的深入了解,于是就准备写几篇文章来记录下Mysql各种事物和索引的情况下出现死锁的情况。

今天就介绍下在并发插入的情况下,哪几种情况会出现死锁:

INNODB下的各种锁

在介绍锁的时候只会介绍跟本节相关的锁,而且只会讲述大概是什么,至于锁的更加详细的讲解可能会到以后再详细介绍。

阅读更多

数据库调优(一)

开篇

在上一篇文章中,我们有一个表,里面的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> select * from org_copy;
+--------+-----------------+---------------+----------+
| org_id | org_name | org_parent_id | org_copy |
+--------+-----------------+---------------+----------+
| 1 | 一级部门 | 0 | 1 |
| 2 | 一一级部门 | 0 | 2 |
| 3 | 1.1级部门 | 1 | 3 |
| 4 | 1.2级部门 | 1 | 4 |
| 5 | 1.1.1部门 | 3 | 5 |
| 6 | 1.1.2部门 | 3 | 6 |
| 7 | 1.1.1.1部门 | 5 | 7 |
| 8 | 1.3部门 | 1 | 8 |
| 9 | 1.2.1部门 | 4 | 9 |
+--------+-----------------+---------------+----------+
9 rows in set (0.00 sec)

这应该是一个很基本的一个mysql表,同时我们在上一篇文章中,也执行了如下SQL。

1
2
3
4
5
6
7
8
mysql> explain SELECT * FROM org_copy WHERE org_name>'一级部门' and  org_parent_id=1;
+----+-------------+----------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | org_copy | NULL | range | index_name | index_name | 768 | NULL | 1 | 11.11 | Using index condition |
+----+-------------+----------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

阅读更多

数据库最左原则以及理解

本次的实验是基于Mysql8版本。首先在数据库中有一个表,其结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> show create table org;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| org | CREATE TABLE `org` (
`org_id` int(5) NOT NULL,
`org_name` varchar(255) DEFAULT NULL,
`org_parent_id` int(5) DEFAULT NULL,
PRIMARY KEY (`org_id`),
KEY `index_name` (`org_name`,`org_parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

可以看到在这个表中,有一个主键org_id以及一个联合索引index_name。其他的并无特别之处。

最左原则

在Mysql里面,有一个最左原则,官网的介绍如下:

阅读更多

在Mysql中使用变量进行复杂的查询(一)

注意,此文章使用的Mysql变量均是用户变量

简介

首先看一个需求,有如下数据表:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from t1 order by area_id;
+---------+-----------+
| area_id | order_num |
+---------+-----------+
| 1 | 22 |
| 1 | 10 |
| 1 | 10 |
| 2 | 10 |
| 2 | 10 |
| 2 | 22 |
| 3 | 10 |
+---------+-----------+
7 rows in set (0.14 sec)

可以看到,这是一个很非常普通的数据表。

阅读更多

MySql之binlog的使用(一)

背景

假设有一个如下的业务场景如下:
需要记录一个商品或者股票的实时价格,每一个小时记录一次,而商品或者股票的数量十分多,这时业务发展到一定的程度之后就需要考虑数据库的设计。首先商品每个小时的价格肯定是需要入库的。其次每小时的购买人群以及各种埋点数据随之一起也要入库。以便于日后的数据分析。

解决方案

随着数据量的增大,一般的解决方案是设置索引,然后再考虑是进行垂直还是水平分库分表。

但是一旦使用水平分库分表就会无形之间增加开发的复杂程度,而且分库分表之后考虑的各种因素也会随之而来增加数倍。例如各种表的唯一ID以及如何进行维度的划分。

阅读更多

对数据库事物的理解

什么是事物

事物通俗的来讲就是就是一组操作事件,可以类比于Java里面的原子操作。在一个事物中,要么全部成功,要么就是全部失败。

mysql中的事物

在Mysql的innodb中,事物的默认级别是 可重复读,在该级别下,事物可能出现幻读。出现幻读的情况是该引擎为行级锁,导致mysql在进行一个事物的时候只会锁定与该事物有关的几行。

示例如下:

阅读更多

mysql的一些总结

前言

今天突然有一个写sql的机会,但是是手写,不像之前那样可以在数据库上做测试。这突然让我感觉有的语法有点生疏了,所以乘着这个机会来做一个全部的梳理。

groupby和where的顺序:

今天是有两表做一个等值连接查询的,在这里应该是先where之后再进行group by,group by 是对where条件过滤之后再进行分组处理,所以where在前。

group by

阅读更多

MySql和时间相关的查询(二)

DATE_ADD():

这个函数可以将日期往前加上规定的年,月或者日,从而方便统计,例如需要统计本月的某些数据的话,一般来讲肯定是只需要大于本月月初即可,但是为了考虑程序的健壮性的话肯定是需要再加一个限制条件,比如说小于下个月1号。那么就需要一个一个DATE_ADD()函数:

1
2
3
4
5
6
SELECT
*
FROM
table
WHERE time_columns > CONCAT(LEFT(NOW() - INTERVAL 0 MONTH, 7), '-01')
AND time_columns < DATE_ADD(CURDATE()-DAY(CURDATE())+1,INTERVAL 1 MONTH);

这条sql便是求的本月的数据。同时在这里也对当前时间的函数进行一个对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mysql> SELECT CURDATE();
+------------+
| CURDATE() |
+------------+
| 2018-03-28 |
+------------+
1 row in set (0.00 sec)

mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2018-03-28 15:07:15 |
+---------------------+
1 row in set (0.00 sec)

mysql> select CURTIME();
+-----------+
| CURTIME() |
+-----------+
| 15:07:39 |
+-----------+
1 row in set (0.00 sec)

阅读更多

在mysql5.7版本中使用groupby所需要注意的

什么是ONLY_FULL_GROUP_BY 模式

先看在mysql 5.7版本中的一个的group by,以下是这个数据库表:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from testgroupby;
+---------+-----------+------------+--------------+
| user_id | user_name | user_score | user_subject |
+---------+-----------+------------+--------------+
| 1 | 张三 | 99 | 语文 |
| 2 | 张三 | 90 | 数学 |
| 3 | 张三 | 80 | 英语 |
| 4 | 李四 | 99 | 语文 |
| 5 | 王五 | 85 | 语文 |
| 6 | 李四 | 91 | 数学 |
| 7 | 王五 | 100 | 英语 |
+---------+-----------+------------+--------------+
7 rows in set (0.00 sec)

这是一个学生成绩数据库表。那么在MySQL5.7版本中执行它的话是会出现一个error的。如下所示:

1
2
3
mysql> select * from testgroupby group by user_name;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'login.testgroupby.user_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

阅读更多

记一次sql和时间段查询有关的语句

前言

由于自己有点需求需要在mysql中按照时间段进行查询,而自己又对这些不太了解,所以趁着这次机会将mysql和时间段相关的查询语句做一个记录:

常用函数:

DATE_SUB()函数

DATE_SUB(date,INTERVAL expr type)这个函数的date是一个时间表达式,一般取得是数据库中的一个字段。后面的INTERVAL一般来讲是不变的,expr一般是一个时间段,代表过去的,比如是30天,那么这里就是30,若是60,这里就是60,type则表示的是一个时间属性(可能表达的不是很准确),如下:

阅读更多