为什么有些大厂不建议MySQL使用Text类型?(四)

开课吧开课吧锤锤2021-04-12 09:58

    Java编程语言是一种简单、面向对象、分布式、解释型、健壮安全、与系统无关、可移植、高性能、多线程和动态的语言。如今Java已经广泛应用于各个领域的编程开发。

Java

    RDS实例被锁定

    背景描述

    公司每个月都会做一些营销活动,有个服务apush活动推送,单独部署在高可用版的RDSforMySQL5.7,配置是4C8G150G磁盘,数据库里也就4张表,晚上22:00下班走的时候,rds实例数据使用了50G空间,第二天早晨9:30在地铁上收到钉钉告警短信,提示push服务rds实例由于diskisfull被lockedwith—read-only,开发也反馈,应用日志报了一堆MySQLerror。

    问题分析

    通过DMS登录到数据库,看一下那个表最大,发现有张表push_log占用了100G+,看了下表结构,里面有两个text字段。

request text default '' comment '请求信息',
response text default '' comment '响应信息'
mysql>show  table status like 'push_log';

    发现Avg_row_length基本都在150KB左右,Rows=78w,表的大小约为780000*150KB/1024/1024=111.5G。

    通过主键update也很慢

insert into user(name,age,gender,info) values('thooo', 35, 'M', repeat('c',65535);
insert into user(name,age,gender,info) values('thooo11', 35, 'M', repeat('d',65535);
insert into user(name,age,gender,info) select name,age,gender,info from user;
Query OK, 6144 rows affected (5.62 sec)
Records: 6144  Duplicates: 0  Warnings: 0                                        
[root@barret] [test]>select count(*) from user;
+----------+
| count(*) |
+----------+
|    24576 |
+----------+
1 row in set (0.05 sec)

    做update操作并跟踪。

mysql> set profiling = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> update user set info = repeat('f',65535) where id = 11;
Query OK, 1 row affected (0.28 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> show profiles;
+----------+------------+--------------------------------------------------------+
| Query_ID | Duration   | Query                                                  |
+----------+------------+--------------------------------------------------------+
|        1 | 0.27874125 | update user set info = repeat('f',65535) where id = 11 |
+----------+------------+--------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show profile cpu,block io for query 1;  
+----------------------+----------+----------+------------+--------------+---------------+
| Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting             | 0.000124 | 0.000088 |   0.000035 |            0 |             0 |
| checking permissions | 0.000021 | 0.000014 |   0.000006 |            0 |             0 |
| Opening tables       | 0.000038 | 0.000026 |   0.000011 |            0 |             0 |
| init                 | 0.000067 | 0.000049 |   0.000020 |            0 |             0 |
| System lock          | 0.000076 | 0.000054 |   0.000021 |            0 |             0 |
| updating             | 0.244906 | 0.000000 |   0.015382 |            0 |         16392 |
| end                  | 0.000036 | 0.000000 |   0.000034 |            0 |             0 |
| query end            | 0.033040 | 0.000000 |   0.000393 |            0 |           136 |
| closing tables       | 0.000046 | 0.000000 |   0.000043 |            0 |             0 |
| freeing items        | 0.000298 | 0.000000 |   0.000053 |            0 |             0 |
| cleaning up          | 0.000092 | 0.000000 |   0.000092 |            0 |             0 |
+----------------------+----------+----------+------------+--------------+---------------+
11 rows in set, 1 warning (0.00 sec)

    可以看到主要耗时在updating这一步,IO输出次数16392次,在并发的表上通过id做update,也会变得很慢。

    group_concat也会导致查询报错

    在业务开发当中,经常有类似这样的需求,需要根据每个省份可以定点医保单位名称,通常实现如下:

select group_concat(dru_name) from t_drugstore group by province;

    其中内置group_concat返回一个聚合的string,最大长度由参数group_concat_max_len(MaximumallowedresultlengthinbytesfortheGROUP_CONCAT())决定,默认是1024,一般都太短了,开发要求改长一点,例如1024000。

    当group_concat返回的结果集的大小超过max_allowed_packet限制的时候,程序会报错,这一点要额外注意

    以上内容由开课吧老师敖丙提供,更多Java教程尽在开课吧广场Java教程频道。

有用
分享