前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL实际应用的两个案例

MySQL实际应用的两个案例

作者头像
AsiaYe
发布2019-11-06 17:16:32
1.2K0
发布2019-11-06 17:16:32
举报
文章被收录于专栏:DBA随笔DBA随笔

01

alter table引发的一个问题

今天早晨,有个业务方提了个需求,是需要把一个表里的字段从date格式直接变成int格式,目的是为了去掉日期格式中间的短横线,类似2019-09-01变成20190901,也就是需要使用alter table的方法修改字段,这种操作一般在线上是不支持的,一般情况下,只有从tinyint改成int,或者从int改成unsigned int这种类型的转换,才会在线上的表做,这种跨类型的,一般不建议直接修改。

我首先询问了一下他表里面的数据量,得到的反馈是这个表是个配置表,数据量就30来条,这我就很放心了,这么小的数据量,即使出了问题,那么恢复起来也比较容易,为了以防万一,我现在测试环境上做了个测试:

代码语言:javascript
复制
mysql@127.0.0.1:yeyztest 10:47:18>>create table test14 (id int primary key,count_date date);   
Query OK, 0 rows affected (0.08 sec)

mysql@127.0.0.1:yeyztest 10:47:50>>insert into test14 values (1,'2019-09-28');
Query OK, 1 row affected (0.01 sec)

mysql@127.0.0.1:yeyztest 10:48:28>>select * from test14;
+----+------------+
| id | count_date |
+----+------------+
|  1 | 2019-09-28 |
+----+------------+
1 row in set (0.00 sec)

mysql@127.0.0.1:yeyztest 10:48:34>>alter table test14 modify count_date int ;
Query OK, 1 row affected (0.02 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql@127.0.0.1:yeyztest 10:48:58>>select *from test14;
+----+------------+
| id | count_date |
+----+------------+
|  1 |   20190928 |
+----+------------+
1 row in set (0.00 sec)

创建了一个test14的表,里面包含两个字段,一个是id,一个是count_date,其中id是int类型的,count_date是date类型的,然后直接进行了一个alter表的修改操作,发现结果和预期的一致。这样就放心了,然后在线上的环境也操作了一下,结果傻眼了。。。

代码语言:javascript
复制
mysql@127.0.0.1 10:50:20>>select * from XXXX;          
+----+------------+------------+----------+----------+----------+---------+---------+---------+
| id | count_date | count_type | count1   | count2   | count3   | count4  | count5  | count6  |
+----+------------+------------+----------+----------+----------+---------+---------+---------+
| 11 | 2019-09-28 |          1 |  2906.00 |  2123.00 |  1675.00 | 1347.00 | 1144.00 |  984.00 |
| 12 | 2019-09-28 |          2 |     0.83 |     0.81 |     0.65 |    0.61 |    0.54 |    0.36 |
| 13 | 2019-09-26 |          1 |  2532.00 |  1623.00 |  1245.00 |  942.00 |  789.00 |  681.00 |
----------------------
| 42 | 2019-10-09 |          2 |     0.97 |     0.98 |     0.94 |    0.85 |    0.62 |    0.35 |
+----+------------+------------+----------+----------+----------+---------+---------+---------+
32 rows in set (0.00 sec)

mysql@127.0.0.1 10:50:35>>alter table XXXX modify count_date int;
Query OK, 32 rows affected, 32 warnings (0.11 sec)
Records: 32  Duplicates: 0  Warnings: 32

mysql@127.0.0.1  11:04:42>>select * from XXXX ;                       
+----+------------+------------+----------+----------+----------+---------+---------+---------+
| id | count_date | count_type | count1   | count2   | count3   | count4  | count5  | count6  |
+----+------------+------------+----------+----------+----------+---------+---------+---------+
| 11 |       2019 |          1 |  2906.00 |  2123.00 |  1675.00 | 1347.00 | 1144.00 |  984.00 |
| 12 |       2019 |          2 |     0.83 |     0.81 |     0.65 |    0.61 |    0.54 |    0.36 |
| 13 |       2019 |          1 |  2532.00 |  1623.00 |  1245.00 |  942.00 |  789.00 |  681.00 |
| 14 |       2019 |          2 |     0.85 |     0.84 |     0.74 |    0.69 |    0.57 |    0.34 |
| 15 |       2019 |          1 |  2494.00 |  1610.00 |  1248.00 |  945.00 |  786.00 |  669.00 |
| 16 |       2019 |          2 |     0.85 |     0.82 |     0.69 |    0.68 |    0.54 |    0.35 |
| 17 |       2019 |          1 |  2424.00 |  1515.00 |  1129.00 |  873.00 |  709.00 |  605.00 |
| 18 |       2019 |          2 |     0.84 |     0.84 |     0.74 |    0.72 |    0.60 |    0.41 |
| 19 |       2019 |          1 |    88.00 |    60.00 |    40.00 |   30.00 |   23.00 |   20.00 |
| 20 |       2019 |          2 |     0.84 |     0.82 |     0.65 |    0.43 |    0.48 |    0.30 |
| 21 |       2019 |          1 | 31332.00 | 17783.00 | 12596.00 | 9692.00 | 8311.00 | 7181.00 |
| 22 |       2019 |          2 |     0.84 |     0.84 |     0.77 |    0.92 |    0.72 |    0.36 |
| 23 |       2019 |          1 | 28173.00 | 16656.00 | 12052.00 | 9262.00 | 7722.00 | 6472.00 |
| 24 |       2019 |          2 |     0.95 |     0.95 |     0.91 |    0.85 |    0.61 |    0.34 |

第二列直接全部变成2019了,这下坏了,直接给截断了,这到底是为什么?来不及想了,先回复数据吧,因为只有30来条数据,就直接拼SQL的方法给恢复了。

后面静下心来想这个问题,为什么测试环境和线上环境的结果不一样呢?详细查看了一番之后,发现问题出在了数据库的版本上,线上的版本是老版本5.5.19,而测试环境是5.7.16,这样问题就明确了,在5.7.16上面,直接变更字段从date类型到int类型,则会去掉date类型的短横线,而在5.5.19版本上,如果进行变更,则会发生截断。

这让我想起了上个礼拜听一个报告的时候,一位行业内老师说的一句话:永远选择最好的机器,用最新的数据库版本,这样能解决你很大一部分问题。确实是,旧的版本还是有些问题处理的不到位,所以才会被迭代。

通过这个事情,有以下几个小收获吧,第一,在线上操作之前,需要现在测试环境搞一把,确认无误之后再进行操作,第二,任何操作之前,都要想到回滚方案,出故障没法解决的操作,我劝大家还是不要做。

02

关于distinct和order by 的一个问题

之前讲过关于MySQL5.7版本的一些参数,其中包含了sql_mode,这个参数是控制MySQL服务的SQL运行模式,5.7版本的模式更为严格,SQL mode参数里面包含大约7个项,今天我遇到的问题主要是关于only_full_group_by相关的,这个参数,说白了就是一个SQL,select出来的字段中需要包含group by出来的字段,关于这个问题,之前的6月27日的文章中有说到过。

今天遇到的问题是,一个业务方写了一个sql,类似于select distinct a,b from table order by c;

然后一直报错,内容是Expression #1 of ORDER BY clause is not in select list.也就是说,order by的字段c不在select的字段a和b当中,然而,去掉了这个SQL中的distinct之后,这个SQL执行起来就没有错误了。

一开始,对于这个错误,我还没有想明白为什么,后面举了个例子想了想,确实是不应该这样。为了方便理解,我写个例子:

代码语言:javascript
复制
-----------
|A   B   C|
-----------
|1   2   3|
-----------
|2   2   4|
-----------
|1   2   5|
-----------

例如这样的一个表,其中a b c为这个表的三个字段,上面的SQL:

select distinct a,b from table order by c;

首先要对a b这个组合去重,我们可以看到,这个组合中,a=1,b=2的记录有两条,而这两条记录的c值是不一样的,那么到底用哪一条记录呢?

如果使用第一条记录c=3,那么按照c字段进行order by 的时候,a=1,b=2的记录就排在a=2,b=2的记录前面;

如果使用第二条记录c=5,那么按照c字段进行order by 的时候,a=1,b=2的记录就排在a=2,b=2的记录后面;

使用不同的记录会产生不同的排序结果,那么MySQL怎么知道使用哪一条记录呢?答案是蒙圈了。所以这种SQL就是不被允许的,如果去掉了distinct,那么这样的SQL其实是没有歧义的,也就被允许了。

今天这两个小案例虽然看起来不起眼,但是在实际应用中,还是需要多注意,否则很容易出现问题,今天就到这里吧。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档