狠狠撸

狠狠撸Share a Scribd company logo
基于滨苍苍辞诲产开发最佳实践

    新媒传信
    吴炳锡
About me
新媒传信(飞信)
 新技术研发部   @吴炳锡   数据库架构师

 职责:
 数据库基础平台研发
 面向公司各部门提供数据库技术支持

 业余:
 北京MySQL活动发起者
大纲
? 案例一:为什么 MySQL这么慢
 – 案例一分析
 – 讨论解决方案
 – 总结经验及运用
? 案例二: 死锁
 – 案例二 分析
 – Innodb锁的类型识别
 – 总结经验及运用
? 总结
案例



案例一:为什么Insert这么慢
案例一:为什么Insert这么慢
? 背景
   向一个表进行insert数据,为啥一秒钟才能写入500条
  (有可能更少)
? 表结构:
  CREATE TABLE `t1_rnd` (
     `id` int(10) unsigned NOT NULL ,
    `c1` varchar(64) NOT NULL,
    `c2` varchar(255) DEFAULT NULL,
      `c3` int(10) unsigned DEFAULT '0',
     PRIMARY KEY (`id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
? 写入程序: 备注中
案例一:为什么insert这么慢
$i_end = (int) '999999999‘;
$i_start = 1000000000;
for ($i = $i_start; $i < $i_end; $i++) {
    $x = mt_rand();
 $sql = "INSERT INTO t1_rnd
   VALUES($x, 'name_$x', 'desc_$x', $i)";
 $res = $pdo->exec($sql);
...
}
案例一:为什么insert这么慢
记数从:100000 开始                ok 101282 w, per: 1079 /s
ok 100503 w, per: 12307 /s   ok 101283 w, per: 1093 /s
ok 100504 w, per: 13369 /s   ok 101284 w, per: 836 /s
...                          ok 101285 w, per: 942 /s
ok 100508 w, per: 14082 /s   ok 101286 w, per: 1021 /s
                             ok 101287 w, per: 1033 /s
ok 100509 w, per: 11058 /s
                             ok 101288 w, per: 816 /s
ok 100510 w, per: 12853 /s   ok 101289 w, per: 802 /s
…                            ok 101290 w, per: 1040 /s
ok 101201 w, per: 15592 /s   ok 101291 w, per: 778 /s
ok 101202 w, per: 11037 /s   ok 101292 w, per: 776 /s
ok 101203 w, per: 13454 /s   ...
ok 101204 w, per: 12482 /s   ok 101360 w, per: 618 /s
ok 101205 w, per: 7162 /s    ok 101361 w, per: 611 /s
                             ok 101362 w, per: 580 /s
ok 101206 w, per: 6323 /s
                             ok 101363 w, per: 593 /s
ok 101207 w, per: 4655 /s    ...
ok 101208 w, per: 6212 /s    ok 101372 w, per: 563 /s
ok 101209 w, per: 3960 /s    ok 101373 w, per: 554 /s
ok 101210 w, per: 2559 /s    ok 101374 w, per: 504 /s
ok 101211 w, per: 2170 /s    ok 101375 w, per: 547 /s
...                          ok 101376 w, per: 569 /s
                             ...
案例一分析
? 查看基本情况
 –   mysql> select count(*) from t1_rnd;
 –   +----------+
 –   | count(*) |
 –   +----------+
 –   | 13719413 |
 –   +----------+
 –   1 row in set (12 min 14.59 sec)
? 文件大小:
 – -rw-rw---- 1 mysql3306 mysql 8.5K 08-09 15:01 t1_rnd.frm
 – -rw-rw---- 1 mysql3306 mysql 1.4G 08-09 15:50 t1_rnd.ibd
案例一分析
? 查看基本情况:
 – 通过Percona-Server的慢日值功能可以查看一下count有多少个
   page被读到,读了多少行。
 – mysql>set global log_slow_verbosity=full;
 – mysql>select count(*) from t1_rnd;
 查看慢日值
慢日值内容:
# Thread_id: 36 Schema: wubx Last_errno: 0 Killed: 0
# Query_time: 719.255557 Lock_time: 0.000051 Rows_sent: 1 Rows_examined:
    13719413 Rows_affected: 0 Rows_read: 18446744073693256119
# Bytes_sent: 70 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0
# InnoDB_trx_id: 4A0B331
# QC_Hit: No Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No
# Filesort: No Filesort_on_disk: No Merge_passes: 0
# InnoDB_IO_r_ops: 74732 InnoDB_IO_r_bytes: 1224409088 InnoDB_IO_r_wait:
    713.597767
# InnoDB_rec_lock_wait: 0.000000 InnoDB_queue_wait: 0.000000
# InnoDB_pages_distinct: 65254
SET timestamp=1312882181;
select count(*) from t1_rnd;
? 基本分析:
 mysql> select 65254*16/1024;
 – +---------------+
 – | 65254*16/1024 |
 – +---------------+
 – | 1019.5938 |
 – +---------------+
 计算一下数据大小:
 –   mysql> select (4+30+30+4)*13719413/1024/1024;
 –   +--------------------------------+
 –   | (4+4+30+30)*13719413/1024/1024 |
 –   +--------------------------------+
 –   |               889.70192337 |
 –   +--------------------------------+
案例一分析
? 思考问题:
 – 为什么我们计算需要存储该表的大小和实质物
   理大小相差那么大呢?
   ? 是索引增加了文件大小?
 – 为什么count那么慢,Rows_read:
   18446744073693256119 !!!!
案例一分析
? 分析归纳:
 文件大小超过计算:
  ? 碎片产生的原因是Innodb表数据本身及索引都属
    于btree结构。
  ? Innodb表按主建有序的存放(Cluster Index)
案例一分析
? Count统计太慢:
   ? Innodb本身没这方计数器,如果进行无条件
     的count实质上相当于把表的btree page全部
     读取一次。
   ? 对于本身碎片很严重的表,这种全表扫描会
     被成一很严重的随机IO操作
   ? 那个Read_Rows很大数据,从实质上理解
     是错误的,这就是Bug.
? 从测试数据来看在写入1200万前,性能还能接
  受。
   ? 是不是可以考虑对于大表进行拆表处理?
   ? 如果该表存在range类的操作,拆表是不是最佳的
     方式呢?
? 对于有碎片明显的表,如何处理能让快点呢?
? 对于无条件count innodb做了什么?
讨论解决方案
看看表碎片比较少的情况的操作:
? 对现存的表碎片整理的操作:
  mysql> alter table theme_irnd engine=Innodb;
  Query OK, 13719413 rows affected (34 min 48.24 sec)
  ? 整理后文件大小:
  -rw-rw---- 1 mysql3306 mysql 848M 08-09 18:23 theme.ibd
  mysql> select count(*) from theme;
  +----------+
  | count(*) |
  +----------+
  | 13719413 |
  +----------+
  1 row in set (4.92 sec)

? 如针对range操作,这样是不是已很好了
? 针对range的在加速:
    mysql> create index idx_c3 on t1_rnd(c3);
    Query OK, 0 rows affected (44.37 sec)
    mysql> select count(*) from t1_rnd;
    +----------+
    | count(*) |
    +----------+
    | 13719413 |
    +----------+
    1 row in set (1.84 sec)

? 什么情况,从原来的
   12 min 14.59 sec->4.92 sec->1.84 sec?
讨论解决方案
? 对于无条件count innodb做了什么?
添加完idx_c3索引后:
# Thread_id: 44 Schema: wubx Last_errno: 0 Killed: 0
# Query_time: 1.841461 Lock_time: 0.000051 Rows_sent: 1 Rows_examined:
    13719413 Rows_affected: 0 Rows_read: 13719413
# Bytes_sent: 70 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0
# InnoDB_trx_id: 4A0B89B
# QC_Hit: No Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk:
    No
# Filesort: No Filesort_on_disk: No Merge_passes: 0
# InnoDB_IO_r_ops: 0 InnoDB_IO_r_bytes: 0 InnoDB_IO_r_wait: 0.000000
# InnoDB_rec_lock_wait: 0.000000 InnoDB_queue_wait: 0.000000
# InnoDB_pages_distinct: 12252
SET timestamp=1312970168;
select count(*) from t1_rnd;
? 为什么用普通索引进行的count比PK快呢?
总结经验及运用
? 总结:
 – 在写入数据时保证主建是有顺的从小到大的方
   式写入
 – 对于Innodb要求快速写入的表添加一列自增的
   自建做为索引
 – 对于Innodb表的使用要保持一个好的习惯,尽
   量基于唯一索引去访问数据(排除range)
 – 如果对于Innodb有大量的update操作,同时又
   有大量的range操作,请考虑定期进行整理碎
   片
总结经验及运用
? 验证:
  同样的表结构,在写入程序做以下调整:
 for ($i = $i_start; $i < $i_end; $i++) {
     $x = $i;
  $sql = "INSERT INTO t1_rnd
    VALUES($x, 'name_$x', 'desc_$x', $i)";
  $res = $pdo->exec($sql);
 ...
 }
总结经验及运用
计数:100000W开始                 ...
ok 100498 w, per: 21769 /s   ok 102991 w, per: 21515 /s
ok 100499 w, per: 21384 /s
ok 100500 w, per: 21770 /s
                             ok 102992 w, per: 21772 /s
ok 100501 w, per: 21376 /s   ok 102993 w, per: 18120 /s
ok 100502 w, per: 21749 /s   ok 102994 w, per: 19615 /s
...                          ok 102995 w, per: 21163 /s
ok 101380 w, per: 21624 /s   ok 102996 w, per: 21782 /s
ok 101381 w, per: 21329 /s   ok 102997 w, per: 21377 /s
ok 101382 w, per: 21632 /s
ok 101383 w, per: 21592 /s
                             ok 102998 w, per: 21705 /s
ok 101384 w, per: 21377 /s   ok 102999 w, per: 13881 /s
ok 101385 w, per: 18434 /s   ok 103000 w, per: 20969 /s
ok 101386 w, per: 19711 /s   ...
...
                             写入到3000W行数据性能也很好
总结经验及运用
? 物理文件大小:
? -rw-rw---- 1 mysql3306 mysql 8.5K 08-09
  15:50 theme.frm
? -rw-rw---- 1 mysql3306 mysql 1.9G 08-09
  16:19 theme.ibd
总结经验及运用
? 运用思考下面类型的表如何设计:
 – 用户表(User)的设计
 – 好友关系表
 – LOG类型的表
总结经验及运用
? 进阶思考:
 – Update会给表带来分页操作吗?
 – Delete会对PAGE有影响吗?


? 如何优化UPDATE&DELETE
案例二:死锁
案例二:死锁
? 背景:
  利用show engine innodb statusG;
  查看LATEST DETECTED DEADLOCK部分经常有死锁现象

  死锁语句:
DELETE FROM GRP_OfflineNotify        WHERE
  UserId = 852577338 AND GroupId = 33990861 AND
  NotifyType = 10
DELETE FROM GRP_OfflineNotify        WHERE
  UserId = 825749088 AND GroupId = 33990861 AND
  NotifyType = 10
案例二 分析
? 了解LATEST DETECTED DEADLOCK :
>show engine innodb statusG;
LATEST DETECTED DEADLOCK
------------------------
这个死锁信息发生的时间
*** (N) TRANSACTION:
   死锁的语句及相关的信息
*** (N) WAITING FOR THIS LOCK TO BE
   GRANTED:
   死锁的原因
案例二 分析
?   死锁原因分析:
mysql> explain select * from GRP_OfflineNotify where UserId=852577338 and
    GroupId=33990861 and NotifyType=10G;
** 1. row **
         id: 1
 select_type: SIMPLE
      table: GRP_OfflineNotify
       type: ref
possible_keys:
    IX_GRP_OfflineNotify_GroupId_NotifyType,IX_GRP_OfflineNotify_UserId
        key: IX_GRP_OfflineNotify_GroupId_NotifyType
    key_len: 5
        ref: const,const
       rows: 1                                          IX_GRP_OfflineNotify_Group
      Extra: Using where                                        Id_NotifyType
1 row in set (0.00 sec)                                      (GroupId, NotifyType)
                                                             普通索引
案例二 分析
? 原因归纳:
     利用
  IX_GRP_OfflineNotify_GroupId_NotifyType索引
  去访问数据,而这个索引并不唯一,所以造成了
  锁的区间较大,造成两个事务相互冲突死锁。

另外:
  也可以参考show engine innodb statusG;中的
 死锁部分中: WAITING FOR THIS LOCK TO BE
 GRANTED
案例二 分析
? 再回到问题上思考:
  这个SQL是做什么的?
  需要锁这么大的区间吗?

? 死锁语句:
DELETE FROM GRP_OfflineNotify
  WHERE         UserId = 852577338 AND
  GroupId = 33990861 AND NotifyType = 10
DELETE FROM GRP_OfflineNotify
  WHERE         UserId = 825749088 AND
  GroupId = 33990861 AND NotifyType = 10
案例二 分析
? 非唯一索引Delete死锁原因:
               root


        brach1
                                    5: col2= 3399086 ,col3=10,…
          Leaf 1
    Sec Ind1          PK     loc   1001:col2= 3399086 ,col3=10,…
                             k
3399086        10     5      X     1006:col2= 3399086 ,col3=10,…
3399086        10     1001   X
3399086        10     1006   X
                                           Table Redords
…
96257735 11           2
6
? 解决办法:
 – 创建新索引:

     create index IX_GRP_OfflineNotify_GroupId
 _UserId_NotifyType on GRP_OfflineNotify(Grou
 pId,UserId,NotifyType);

 – 删除旧索引:

    drop index IX_GRP_OfflineNotify_GroupId_
 NotifyType on GRP_OfflineNotify;
? Innodb支持的锁类型:
 – Record lock
 – Next Key lock
 – Gap lock
 – Table lock

? 高并环境事务隔离级别:
  READ-COMMITTED
Innodb锁的类型识别
? Gap-lock
   – 这个锁影响Insert操作。
   假设一个索引包括5,7利用这个索引访问过的
     取出结果为5,7相关记录,但同时别的
     session需要insert一个索引为6的索引,这个就
     需要等待。
   该锁在:READ-COMMITTED隔离级别下不工作。
? Table-lock
   属于显式声明的,可以忽略。
总结经验及运用
? Innodb索引分情况:
                                                       root
            root

                                                         brach1
       brach1

       Leaf 1                                          Leaf 1
Sec Ind1    PK                        Pk       Table other recoder
1           5                         1        col2=‘wubx’, col3=‘775’,…
5           1                         2        col2=‘liuxin’,col3=‘123’,…
…                                     …
99          2                         5        Col2=‘zbr’,col3=‘1000’…

                   Select * from tb where sec_ind1=1
总结经验及运用
? 变长字段处理:

                    …   Prefix(768B)   …
                                           COMACT

                                                OverFlow
                                                  page
     20 bytes
 …              …
                DYNAMIC

                          OverFlow
                            page
总结经验及运用
? 讨论个问题:
 – 为什么Innodb表设计中有条:没有特殊的理由
   请给该表添加一个自增的例做主建?
 – 那么有特属的理由又是啥呢?
总结经验及运用
? 运用:
 – 养成基于唯一索引访问数据的习惯
 – Update操作不要去update主建
 – 没有特殊的理由请给你的表添加一个无符号自
   增列做为主建
 – 如果大量的查询是基于条件的range操作,请把
   这个索引做为第二索引
基于滨苍苍辞诲产开发的最佳实践

More Related Content

What's hot (20)

Mysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimizationMysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimization
isnull
?
Mongo db部署架构之优先方案
Mongo db部署架构之优先方案Mongo db部署架构之优先方案
Mongo db部署架构之优先方案
Lucien Li
?
Essential oracle security internal for dba
Essential oracle security internal for dbaEssential oracle security internal for dba
Essential oracle security internal for dba
maclean liu
?
Mongo db部署架构之优先方案
Mongo db部署架构之优先方案Mongo db部署架构之优先方案
Mongo db部署架构之优先方案
Lucien Li
?
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期
yiditushe
?
Mysql 高级优化之 理解查询执行
Mysql 高级优化之 理解查询执行Mysql 高级优化之 理解查询执行
Mysql 高级优化之 理解查询执行
nigel889
?
基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性
babyyellow li
?
人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
Fuzhou University
?
分布式系统缓存设计
分布式系统缓存设计分布式系统缓存设计
分布式系统缓存设计
zhujiadun
?
分布式系统缓存设计
分布式系统缓存设计分布式系统缓存设计
分布式系统缓存设计
aleafs
?
Mysql 高级优化之 逻辑处理
Mysql 高级优化之 逻辑处理Mysql 高级优化之 逻辑处理
Mysql 高级优化之 逻辑处理
nigel889
?
卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
Fuzhou University
?
我对后端优化的一点想法 (2012)
我对后端优化的一点想法 (2012)我对后端优化的一点想法 (2012)
我对后端优化的一点想法 (2012)
james tong
?
惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应
zhaolinjnu
?
翱谤补肠濒别10驳高级安全特性列加密技术
翱谤补肠濒别10驳高级安全特性列加密技术翱谤补肠濒别10驳高级安全特性列加密技术
翱谤补肠濒别10驳高级安全特性列加密技术
maclean liu
?
【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略
【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略
【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略
maclean liu
?
Dog svr
Dog svrDog svr
Dog svr
yxcwf
?
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
maclean liu
?
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
pwesh
?
Mysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimizationMysql introduction-and-performance-optimization
Mysql introduction-and-performance-optimization
isnull
?
Mongo db部署架构之优先方案
Mongo db部署架构之优先方案Mongo db部署架构之优先方案
Mongo db部署架构之优先方案
Lucien Li
?
Essential oracle security internal for dba
Essential oracle security internal for dbaEssential oracle security internal for dba
Essential oracle security internal for dba
maclean liu
?
Mongo db部署架构之优先方案
Mongo db部署架构之优先方案Mongo db部署架构之优先方案
Mongo db部署架构之优先方案
Lucien Li
?
Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期Csdn Emag(Oracle)第二期
Csdn Emag(Oracle)第二期
yiditushe
?
Mysql 高级优化之 理解查询执行
Mysql 高级优化之 理解查询执行Mysql 高级优化之 理解查询执行
Mysql 高级优化之 理解查询执行
nigel889
?
基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性基于linux-HA 的PG高可用性
基于linux-HA 的PG高可用性
babyyellow li
?
人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
人工智慧09冲神经网路(罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
Fuzhou University
?
分布式系统缓存设计
分布式系统缓存设计分布式系统缓存设计
分布式系统缓存设计
zhujiadun
?
分布式系统缓存设计
分布式系统缓存设计分布式系统缓存设计
分布式系统缓存设计
aleafs
?
Mysql 高级优化之 逻辑处理
Mysql 高级优化之 逻辑处理Mysql 高级优化之 逻辑处理
Mysql 高级优化之 逻辑处理
nigel889
?
卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
卷积神经网路(笔测迟丑辞苍+罢别苍蝉辞谤贵濒辞飞+碍别谤补蝉)
Fuzhou University
?
我对后端优化的一点想法 (2012)
我对后端优化的一点想法 (2012)我对后端优化的一点想法 (2012)
我对后端优化的一点想法 (2012)
james tong
?
惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应惭测蝉辩濒展示功能与源码对应
惭测蝉辩濒展示功能与源码对应
zhaolinjnu
?
翱谤补肠濒别10驳高级安全特性列加密技术
翱谤补肠濒别10驳高级安全特性列加密技术翱谤补肠濒别10驳高级安全特性列加密技术
翱谤补肠濒别10驳高级安全特性列加密技术
maclean liu
?
【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略
【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略
【诗檀软件 郭兆伟-技术报告】跨国公司级翱谤补肠濒别数据库备份策略
maclean liu
?
Dog svr
Dog svrDog svr
Dog svr
yxcwf
?
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
maclean liu
?
Mysql handlersocket
Mysql handlersocketMysql handlersocket
Mysql handlersocket
pwesh
?

Similar to 基于滨苍苍辞诲产开发的最佳实践 (20)

探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG
探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG
探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG
YingSiang Geng
?
2011 06-12-lamp-mysql-顾春江
2011 06-12-lamp-mysql-顾春江2011 06-12-lamp-mysql-顾春江
2011 06-12-lamp-mysql-顾春江
thinkinlamp
?
2011 06-12-lamp-mysql
2011 06-12-lamp-mysql2011 06-12-lamp-mysql
2011 06-12-lamp-mysql
pwesh
?
阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化
guiyingshenxia
?
阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化
colderboy17
?
MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220
Jinrong Ye
?
Continuous Delivery Workshop with Ansible x GitLab CI (2nd)
Continuous Delivery Workshop with Ansible x GitLab CI (2nd)Continuous Delivery Workshop with Ansible x GitLab CI (2nd)
Continuous Delivery Workshop with Ansible x GitLab CI (2nd)
Chu-Siang Lai
?
惭测蝉辩濒遇到的一些问题
惭测蝉辩濒遇到的一些问题惭测蝉辩濒遇到的一些问题
惭测蝉辩濒遇到的一些问题
wang tongchao
?
Osc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresqlOsc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresql
OpenSourceCamp
?
110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析
Zoom Quiet
?
数据库极限性能测试
数据库极限性能测试数据库极限性能测试
数据库极限性能测试
helbreathszw
?
MongoDB at Qihoo 360
MongoDB at Qihoo 360MongoDB at Qihoo 360
MongoDB at Qihoo 360
MongoDB
?
腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化
topgeek
?
淘宝数据魔方的系统架构 -长林
淘宝数据魔方的系统架构 -长林淘宝数据魔方的系统架构 -长林
淘宝数据魔方的系统架构 -长林
Shaoning Pan
?
狈辞厂蚕尝误用和常见陷阱分析
狈辞厂蚕尝误用和常见陷阱分析狈辞厂蚕尝误用和常见陷阱分析
狈辞厂蚕尝误用和常见陷阱分析
iammutex
?
腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化
areyouok
?
腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化
topgeek
?
Mysql fast share
Mysql fast shareMysql fast share
Mysql fast share
rfyiamcool
?
摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)
摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)
摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)
Shanda innovation institute
?
探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG
探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG
探索 ISTIO 新型 DATA PLANE 架構 AMBIENT MESH - GOLANG TAIWAN GATHERING #77 X CNTUG
YingSiang Geng
?
2011 06-12-lamp-mysql-顾春江
2011 06-12-lamp-mysql-顾春江2011 06-12-lamp-mysql-顾春江
2011 06-12-lamp-mysql-顾春江
thinkinlamp
?
2011 06-12-lamp-mysql
2011 06-12-lamp-mysql2011 06-12-lamp-mysql
2011 06-12-lamp-mysql
pwesh
?
阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化
guiyingshenxia
?
阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化阿里巴巴 叶正盛 数据库性能量化
阿里巴巴 叶正盛 数据库性能量化
colderboy17
?
MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220MySQL 6.0 下的cluster + replicate - 20080220
MySQL 6.0 下的cluster + replicate - 20080220
Jinrong Ye
?
Continuous Delivery Workshop with Ansible x GitLab CI (2nd)
Continuous Delivery Workshop with Ansible x GitLab CI (2nd)Continuous Delivery Workshop with Ansible x GitLab CI (2nd)
Continuous Delivery Workshop with Ansible x GitLab CI (2nd)
Chu-Siang Lai
?
惭测蝉辩濒遇到的一些问题
惭测蝉辩濒遇到的一些问题惭测蝉辩濒遇到的一些问题
惭测蝉辩濒遇到的一些问题
wang tongchao
?
Osc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresqlOsc scott linux下的数据库优化for_postgresql
Osc scott linux下的数据库优化for_postgresql
OpenSourceCamp
?
110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析110824 knoss-windows系统机制浅析
110824 knoss-windows系统机制浅析
Zoom Quiet
?
数据库极限性能测试
数据库极限性能测试数据库极限性能测试
数据库极限性能测试
helbreathszw
?
MongoDB at Qihoo 360
MongoDB at Qihoo 360MongoDB at Qihoo 360
MongoDB at Qihoo 360
MongoDB
?
腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化
topgeek
?
淘宝数据魔方的系统架构 -长林
淘宝数据魔方的系统架构 -长林淘宝数据魔方的系统架构 -长林
淘宝数据魔方的系统架构 -长林
Shaoning Pan
?
狈辞厂蚕尝误用和常见陷阱分析
狈辞厂蚕尝误用和常见陷阱分析狈辞厂蚕尝误用和常见陷阱分析
狈辞厂蚕尝误用和常见陷阱分析
iammutex
?
腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化
areyouok
?
腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化腾讯大讲堂06 qq邮箱性能优化
腾讯大讲堂06 qq邮箱性能优化
topgeek
?
摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)
摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)
摆贵濒补蝉丑开发者交流闭摆2010.05.30闭补惫尘2虚拟机浅析与补蝉3性能优化(陈士凯)
Shanda innovation institute
?

基于滨苍苍辞诲产开发的最佳实践

  • 2. About me 新媒传信(飞信) 新技术研发部 @吴炳锡 数据库架构师 职责: 数据库基础平台研发 面向公司各部门提供数据库技术支持 业余: 北京MySQL活动发起者
  • 3. 大纲 ? 案例一:为什么 MySQL这么慢 – 案例一分析 – 讨论解决方案 – 总结经验及运用 ? 案例二: 死锁 – 案例二 分析 – Innodb锁的类型识别 – 总结经验及运用 ? 总结
  • 5. 案例一:为什么Insert这么慢 ? 背景 向一个表进行insert数据,为啥一秒钟才能写入500条 (有可能更少) ? 表结构: CREATE TABLE `t1_rnd` ( `id` int(10) unsigned NOT NULL , `c1` varchar(64) NOT NULL, `c2` varchar(255) DEFAULT NULL, `c3` int(10) unsigned DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ? 写入程序: 备注中
  • 6. 案例一:为什么insert这么慢 $i_end = (int) '999999999‘; $i_start = 1000000000; for ($i = $i_start; $i < $i_end; $i++) { $x = mt_rand(); $sql = "INSERT INTO t1_rnd VALUES($x, 'name_$x', 'desc_$x', $i)"; $res = $pdo->exec($sql); ... }
  • 7. 案例一:为什么insert这么慢 记数从:100000 开始 ok 101282 w, per: 1079 /s ok 100503 w, per: 12307 /s ok 101283 w, per: 1093 /s ok 100504 w, per: 13369 /s ok 101284 w, per: 836 /s ... ok 101285 w, per: 942 /s ok 100508 w, per: 14082 /s ok 101286 w, per: 1021 /s ok 101287 w, per: 1033 /s ok 100509 w, per: 11058 /s ok 101288 w, per: 816 /s ok 100510 w, per: 12853 /s ok 101289 w, per: 802 /s … ok 101290 w, per: 1040 /s ok 101201 w, per: 15592 /s ok 101291 w, per: 778 /s ok 101202 w, per: 11037 /s ok 101292 w, per: 776 /s ok 101203 w, per: 13454 /s ... ok 101204 w, per: 12482 /s ok 101360 w, per: 618 /s ok 101205 w, per: 7162 /s ok 101361 w, per: 611 /s ok 101362 w, per: 580 /s ok 101206 w, per: 6323 /s ok 101363 w, per: 593 /s ok 101207 w, per: 4655 /s ... ok 101208 w, per: 6212 /s ok 101372 w, per: 563 /s ok 101209 w, per: 3960 /s ok 101373 w, per: 554 /s ok 101210 w, per: 2559 /s ok 101374 w, per: 504 /s ok 101211 w, per: 2170 /s ok 101375 w, per: 547 /s ... ok 101376 w, per: 569 /s ...
  • 8. 案例一分析 ? 查看基本情况 – mysql> select count(*) from t1_rnd; – +----------+ – | count(*) | – +----------+ – | 13719413 | – +----------+ – 1 row in set (12 min 14.59 sec) ? 文件大小: – -rw-rw---- 1 mysql3306 mysql 8.5K 08-09 15:01 t1_rnd.frm – -rw-rw---- 1 mysql3306 mysql 1.4G 08-09 15:50 t1_rnd.ibd
  • 9. 案例一分析 ? 查看基本情况: – 通过Percona-Server的慢日值功能可以查看一下count有多少个 page被读到,读了多少行。 – mysql>set global log_slow_verbosity=full; – mysql>select count(*) from t1_rnd; 查看慢日值
  • 10. 慢日值内容: # Thread_id: 36 Schema: wubx Last_errno: 0 Killed: 0 # Query_time: 719.255557 Lock_time: 0.000051 Rows_sent: 1 Rows_examined: 13719413 Rows_affected: 0 Rows_read: 18446744073693256119 # Bytes_sent: 70 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0 # InnoDB_trx_id: 4A0B331 # QC_Hit: No Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No # Filesort: No Filesort_on_disk: No Merge_passes: 0 # InnoDB_IO_r_ops: 74732 InnoDB_IO_r_bytes: 1224409088 InnoDB_IO_r_wait: 713.597767 # InnoDB_rec_lock_wait: 0.000000 InnoDB_queue_wait: 0.000000 # InnoDB_pages_distinct: 65254 SET timestamp=1312882181; select count(*) from t1_rnd;
  • 11. ? 基本分析: mysql> select 65254*16/1024; – +---------------+ – | 65254*16/1024 | – +---------------+ – | 1019.5938 | – +---------------+ 计算一下数据大小: – mysql> select (4+30+30+4)*13719413/1024/1024; – +--------------------------------+ – | (4+4+30+30)*13719413/1024/1024 | – +--------------------------------+ – | 889.70192337 | – +--------------------------------+
  • 12. 案例一分析 ? 思考问题: – 为什么我们计算需要存储该表的大小和实质物 理大小相差那么大呢? ? 是索引增加了文件大小? – 为什么count那么慢,Rows_read: 18446744073693256119 !!!!
  • 13. 案例一分析 ? 分析归纳: 文件大小超过计算: ? 碎片产生的原因是Innodb表数据本身及索引都属 于btree结构。 ? Innodb表按主建有序的存放(Cluster Index)
  • 14. 案例一分析 ? Count统计太慢: ? Innodb本身没这方计数器,如果进行无条件 的count实质上相当于把表的btree page全部 读取一次。 ? 对于本身碎片很严重的表,这种全表扫描会 被成一很严重的随机IO操作 ? 那个Read_Rows很大数据,从实质上理解 是错误的,这就是Bug.
  • 15. ? 从测试数据来看在写入1200万前,性能还能接 受。 ? 是不是可以考虑对于大表进行拆表处理? ? 如果该表存在range类的操作,拆表是不是最佳的 方式呢? ? 对于有碎片明显的表,如何处理能让快点呢? ? 对于无条件count innodb做了什么?
  • 16. 讨论解决方案 看看表碎片比较少的情况的操作: ? 对现存的表碎片整理的操作: mysql> alter table theme_irnd engine=Innodb; Query OK, 13719413 rows affected (34 min 48.24 sec) ? 整理后文件大小: -rw-rw---- 1 mysql3306 mysql 848M 08-09 18:23 theme.ibd mysql> select count(*) from theme; +----------+ | count(*) | +----------+ | 13719413 | +----------+ 1 row in set (4.92 sec) ? 如针对range操作,这样是不是已很好了
  • 17. ? 针对range的在加速: mysql> create index idx_c3 on t1_rnd(c3); Query OK, 0 rows affected (44.37 sec) mysql> select count(*) from t1_rnd; +----------+ | count(*) | +----------+ | 13719413 | +----------+ 1 row in set (1.84 sec) ? 什么情况,从原来的 12 min 14.59 sec->4.92 sec->1.84 sec?
  • 18. 讨论解决方案 ? 对于无条件count innodb做了什么? 添加完idx_c3索引后: # Thread_id: 44 Schema: wubx Last_errno: 0 Killed: 0 # Query_time: 1.841461 Lock_time: 0.000051 Rows_sent: 1 Rows_examined: 13719413 Rows_affected: 0 Rows_read: 13719413 # Bytes_sent: 70 Tmp_tables: 0 Tmp_disk_tables: 0 Tmp_table_sizes: 0 # InnoDB_trx_id: 4A0B89B # QC_Hit: No Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No # Filesort: No Filesort_on_disk: No Merge_passes: 0 # InnoDB_IO_r_ops: 0 InnoDB_IO_r_bytes: 0 InnoDB_IO_r_wait: 0.000000 # InnoDB_rec_lock_wait: 0.000000 InnoDB_queue_wait: 0.000000 # InnoDB_pages_distinct: 12252 SET timestamp=1312970168; select count(*) from t1_rnd; ? 为什么用普通索引进行的count比PK快呢?
  • 19. 总结经验及运用 ? 总结: – 在写入数据时保证主建是有顺的从小到大的方 式写入 – 对于Innodb要求快速写入的表添加一列自增的 自建做为索引 – 对于Innodb表的使用要保持一个好的习惯,尽 量基于唯一索引去访问数据(排除range) – 如果对于Innodb有大量的update操作,同时又 有大量的range操作,请考虑定期进行整理碎 片
  • 20. 总结经验及运用 ? 验证: 同样的表结构,在写入程序做以下调整: for ($i = $i_start; $i < $i_end; $i++) { $x = $i; $sql = "INSERT INTO t1_rnd VALUES($x, 'name_$x', 'desc_$x', $i)"; $res = $pdo->exec($sql); ... }
  • 21. 总结经验及运用 计数:100000W开始 ... ok 100498 w, per: 21769 /s ok 102991 w, per: 21515 /s ok 100499 w, per: 21384 /s ok 100500 w, per: 21770 /s ok 102992 w, per: 21772 /s ok 100501 w, per: 21376 /s ok 102993 w, per: 18120 /s ok 100502 w, per: 21749 /s ok 102994 w, per: 19615 /s ... ok 102995 w, per: 21163 /s ok 101380 w, per: 21624 /s ok 102996 w, per: 21782 /s ok 101381 w, per: 21329 /s ok 102997 w, per: 21377 /s ok 101382 w, per: 21632 /s ok 101383 w, per: 21592 /s ok 102998 w, per: 21705 /s ok 101384 w, per: 21377 /s ok 102999 w, per: 13881 /s ok 101385 w, per: 18434 /s ok 103000 w, per: 20969 /s ok 101386 w, per: 19711 /s ... ... 写入到3000W行数据性能也很好
  • 22. 总结经验及运用 ? 物理文件大小: ? -rw-rw---- 1 mysql3306 mysql 8.5K 08-09 15:50 theme.frm ? -rw-rw---- 1 mysql3306 mysql 1.9G 08-09 16:19 theme.ibd
  • 23. 总结经验及运用 ? 运用思考下面类型的表如何设计: – 用户表(User)的设计 – 好友关系表 – LOG类型的表
  • 24. 总结经验及运用 ? 进阶思考: – Update会给表带来分页操作吗? – Delete会对PAGE有影响吗? ? 如何优化UPDATE&DELETE
  • 26. 案例二:死锁 ? 背景: 利用show engine innodb statusG; 查看LATEST DETECTED DEADLOCK部分经常有死锁现象 死锁语句: DELETE FROM GRP_OfflineNotify WHERE UserId = 852577338 AND GroupId = 33990861 AND NotifyType = 10 DELETE FROM GRP_OfflineNotify WHERE UserId = 825749088 AND GroupId = 33990861 AND NotifyType = 10
  • 27. 案例二 分析 ? 了解LATEST DETECTED DEADLOCK : >show engine innodb statusG; LATEST DETECTED DEADLOCK ------------------------ 这个死锁信息发生的时间 *** (N) TRANSACTION: 死锁的语句及相关的信息 *** (N) WAITING FOR THIS LOCK TO BE GRANTED: 死锁的原因
  • 28. 案例二 分析 ? 死锁原因分析: mysql> explain select * from GRP_OfflineNotify where UserId=852577338 and GroupId=33990861 and NotifyType=10G; ** 1. row ** id: 1 select_type: SIMPLE table: GRP_OfflineNotify type: ref possible_keys: IX_GRP_OfflineNotify_GroupId_NotifyType,IX_GRP_OfflineNotify_UserId key: IX_GRP_OfflineNotify_GroupId_NotifyType key_len: 5 ref: const,const rows: 1 IX_GRP_OfflineNotify_Group Extra: Using where Id_NotifyType 1 row in set (0.00 sec) (GroupId, NotifyType) 普通索引
  • 29. 案例二 分析 ? 原因归纳: 利用 IX_GRP_OfflineNotify_GroupId_NotifyType索引 去访问数据,而这个索引并不唯一,所以造成了 锁的区间较大,造成两个事务相互冲突死锁。 另外: 也可以参考show engine innodb statusG;中的 死锁部分中: WAITING FOR THIS LOCK TO BE GRANTED
  • 30. 案例二 分析 ? 再回到问题上思考: 这个SQL是做什么的? 需要锁这么大的区间吗? ? 死锁语句: DELETE FROM GRP_OfflineNotify WHERE UserId = 852577338 AND GroupId = 33990861 AND NotifyType = 10 DELETE FROM GRP_OfflineNotify WHERE UserId = 825749088 AND GroupId = 33990861 AND NotifyType = 10
  • 31. 案例二 分析 ? 非唯一索引Delete死锁原因: root brach1 5: col2= 3399086 ,col3=10,… Leaf 1 Sec Ind1 PK loc 1001:col2= 3399086 ,col3=10,… k 3399086 10 5 X 1006:col2= 3399086 ,col3=10,… 3399086 10 1001 X 3399086 10 1006 X Table Redords … 96257735 11 2 6
  • 32. ? 解决办法: – 创建新索引: create index IX_GRP_OfflineNotify_GroupId _UserId_NotifyType on GRP_OfflineNotify(Grou pId,UserId,NotifyType); – 删除旧索引: drop index IX_GRP_OfflineNotify_GroupId_ NotifyType on GRP_OfflineNotify;
  • 33. ? Innodb支持的锁类型: – Record lock – Next Key lock – Gap lock – Table lock ? 高并环境事务隔离级别: READ-COMMITTED
  • 34. Innodb锁的类型识别 ? Gap-lock – 这个锁影响Insert操作。 假设一个索引包括5,7利用这个索引访问过的 取出结果为5,7相关记录,但同时别的 session需要insert一个索引为6的索引,这个就 需要等待。 该锁在:READ-COMMITTED隔离级别下不工作。 ? Table-lock 属于显式声明的,可以忽略。
  • 35. 总结经验及运用 ? Innodb索引分情况: root root brach1 brach1 Leaf 1 Leaf 1 Sec Ind1 PK Pk Table other recoder 1 5 1 col2=‘wubx’, col3=‘775’,… 5 1 2 col2=‘liuxin’,col3=‘123’,… … … 99 2 5 Col2=‘zbr’,col3=‘1000’… Select * from tb where sec_ind1=1
  • 36. 总结经验及运用 ? 变长字段处理: … Prefix(768B) … COMACT OverFlow page 20 bytes … … DYNAMIC OverFlow page
  • 37. 总结经验及运用 ? 讨论个问题: – 为什么Innodb表设计中有条:没有特殊的理由 请给该表添加一个自增的例做主建? – 那么有特属的理由又是啥呢?
  • 38. 总结经验及运用 ? 运用: – 养成基于唯一索引访问数据的习惯 – Update操作不要去update主建 – 没有特殊的理由请给你的表添加一个无符号自 增列做为主建 – 如果大量的查询是基于条件的range操作,请把 这个索引做为第二索引