美文网首页
2018-12-30

2018-12-30

作者: zhangsanzhu | 来源:发表于2018-12-30 22:56 被阅读0次

    MYSQL - ( 一 )

    事务隔离级别

    • read-uncommitted 三种问题都有
    • read-committed 不可重复读、幻读、
    • repeatable-read 幻读(加上 MVCC 可防止这个问题)
    • serializable 无

    1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

    2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,
    导致事务A多次读取同一数据时,结果 不一致。

    3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,
    但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,
    就好像发生了幻觉一样,这就叫幻读。

    注意 不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。
    解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

    分布式集群 和 主从,怎么样保证节点数据一致 ?

    同步复制:全部写成功了,才返回用户成功(分布式集群)

    异步复制:产生binlog,但不能保证从库一定能接收到(mysql主从),主库挂了,从库数据丢失

    半同步复制: 至少有一个从库可以执行成功

    mysql内部复制方式结构

    [mysql主从结构] --> 5.5-单线程 5.6-多线程

    Bin-log/relay log
    行模式
    buffer pool
    Mysql升序排序速度大于降序排序速度,因为page之间是双链表,page内部是单向链表
    一个page 最大16k,至少要保证有两块数据(因为双向列表),所以一条数据最大只能是8k。单条数据过大的时候,会申请额外内存,page中存储部分数据+额外内存地址

    覆盖索引
    等值索引在前,范围索引在后,比较好
    根据索引估计出的行数大于总行数的30%的时候,会走全表,因为全表是顺序读取,根据索引读取有随机读取,索引在行数大于30%的时候全表更快
    Force index(idx_value)可以强制指定使用某个索引,常在执行计划中使用,生产慎用,因为在数据量改变的时候,固定使用某个索引可能不是最优的,但强制之后,mysql无法自行优化
    Ps: use index(索引1,索引2,索引3),可以让mysql在以上三个索引中选取索引进行查询

    In 条件可以命中索引。

    使用in查询的时候,mysql内部有一个参数5.5的时候是10,5.6之后是一个接近100的值,
    当in里面的数据小于该值的时候,mysql会逐条根据索引分析,然后相加,
    确定索引覆盖数据是否小于总数据的30%,若小于,则走索引;若in里面数据大于该值的时候,
    会根据索引分布估计一个覆盖值出来,并决定是否使用索引。
    explain extended 可以获取优化后的sql语句
    PXC
    MGR

    b+树结构

    • 节点(page) 之间双向链表,节点(page) 里面是单项链表
    • 升序比降序效率高,同一个节点内可能要做反转的;
    • 2个 < page.size < 16K

    索引建立规则

    1. 字段区分度高的-->比如:state见索引就不好,b+tree退化成有序链表
    2. 联合索引:区分度高的放前面
    -- 等值查询
    select a from b where staff_id=1 and customer_id=589;
    
    • INDEX idx_staff(staff_id)+INDEX idx_customer(customer_id)
      这种情况在 5.5 只能用一个索引,在 5.6 加了index merge, 会使用两个索引交集
    • INDEX idx_staff_customer(staff_id, customer_id)
    • INDEX idx_customer_staff(customer_id, staff_id)(最好的方式)
      区分度高的字段放前面,sql语句and的条件顺序没影响.
    -- 范围查询
    SELECT f1 FROM t1 WHERE customer_id = 2 AND payment > 10
    
    • INDEX idx_payment_customer(payment, customer_id)
      第一种会查出>10 然后过滤=2
    • INDEX idx_customer_payment(customer_id, payment))(最好的方式)
    1. 避免冗余索引
    2. 前缀索引
    3. 避免索引过多:写入要更新b+tree

    sql优化

    1. 全表扫描 or 索引扫描
      如果扫描行数超过30%那就全表扫描,直接走主键,认为随机访问代价较高

    2. 链表查询
      关联字段创建索引,如果关联表没有建立索引,那么就会全表扫描的

    3. 批量写入的写法

    INSERT INTO t(id, name) VALUES(1, 'Bea');
    INSERT INTO t(id, name) VALUES(2, 'Belle');
    INSERT INTO t(id, name) VALUES(3, 'Bernice');
    网络开销大
    
    INSERT INTO t(id, name) VALUES(1, 'Bea'), (2, 'Belle'), (3, 'Bernice');
    网络开销小,数量大,执行时间长,死锁概率高,回滚时间长(大小控制在几十左右,经验判断)
    
    1. 避免大事务
      避免事务内的外部依赖,比如mq相应超时,如果当前记录与其他查询操作有阻塞,那么服务将长时间不可用

    2. 死锁,排序基本上能解决

    3. 分页查询
      SELECT id FROM t LIMIT 10000, 10; 需要查询10010条记录,拿最后的10条

      SELECT id FROM t WHERE id > 10000 LIMIT 10 通过额外条件过滤,就不需要扫描全部记录.

    truncate drop delete

    MySQL5.6版本以下:使用truncate table + drop table 替代 drop table
    MySQL5.6版本+ : 直接使用drop table

    为什么要设置不为null,并且要给定默认值.

    Null 列需要更多的存储空间:需要一个额外字节作为判断是否为 NULL 的标志位,
    如果一个!=null的值插入进来,那么page的大小会改变,会发生重平衡.
    使用null是想让数据库做校验,但是数据库是处理存储的,这种校验的逻辑放到上层做才对.

    相关文章

      网友评论

          本文标题:2018-12-30

          本文链接:https://www.haomeiwen.com/subject/dxbblqtx.html