首页新闻招聘找找看知识库
  • 回复:16 浏览:62 2019-12-19 10:52 来自 cn2019

    innodb数据文件 B+树形式组织 主索引文件 主键组织起

     

    B+树节点的关键字就是表的主键

    主索引中  叶子页(leaf page)包含=>数据记录,

                 非叶子节点=>只含主键,术语“聚簇”表示数据行和相邻的键值紧凑地存储在一起,

                                                                 因此这种索引被称为聚簇索引,或聚集索引

     

    为什么innodb引擎下创建的表,必须指定主键的原因

    如果没有显式指定主键,innodb引擎仍然会对该表隐式主键作为聚簇索引

  • cn2019
    2019-12-19 10:54 cn2019
    查询辅助索引的时候会查询两次,首先通过辅助索引得到主键值,然后再查询主索引
    第1楼 回到顶楼
  • cn2019
    2019-12-19 10:56 cn2019
    MyISAM引擎同样也使用B+树组织索引,如下图所示,假设我们的数据不是按照之前的顺序插入的,而是按照图中的是顺序插入表,可以看到MyISAM引擎下,B+树叶子节点中包含的是数据记录的地址(可以简单理解为“行号”),而MyISAM的辅助索引在结构上和主索引没有本质的区别,同样其叶子节点也包含了数据记录的地址,稍微不同的是辅助索引的关键字是允许重复
    第2楼 回到顶楼
  • cn2019
    2019-12-19 10:58 cn2019
    1、Innodb辅助索引的叶子节点存储的不是地址,而是主键值,这样的策略减少了当出现行移动或者数据页分裂时辅助索引的维护工作,虽然使用主键值当作指针会让辅助索引占用更多空间,但好处是,Innodb在移动行时无需更新辅助索引中的主键值,而MyISAM需要调整其叶子节点中的地址。

    2、innodb引擎下,数据记录是保存在B+树的叶子节点(大小相当于磁盘上的页)上,当插入新的数据时,如果主键的值是有序的,它会把每一条记录都存储在上一条记录的后面,但是如果主键使用的是无序的数值,例如UUID,这样在插入数据时Innodb无法简单地把新的数据插入到最后,而是需要为这条数据寻找合适的位置,这就额外增加了工作,这就是innodb引擎写入性能要略差于MyISAM的原因之一
    第3楼 回到顶楼
  • cn2019
    2019-12-19 11:09 cn2019
    mysql的索引有5种:主键索引、普通索引、唯一索引、全文索引、聚合索引(多列索引)。

    唯一索引和全文索引用的很少,我们主要关注主键索引、普通索引和聚合索引。

    1)主键索引:主键索引是加在主键上的索引,设置主键(primary key)的时候,mysql会自动创建主键索引;

    2)普通索引:创建在非主键列上的索引;

    3)聚合索引:创建在多列上的索引
    第4楼 回到顶楼
  • cn2019
    2019-12-19 11:57 cn2019
    nnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!
    第5楼 回到顶楼
  • cn2019
    2019-12-19 14:03 cn2019
    共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
    排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE
    用SELECT .. IN SHARE MODE获得共享锁,主要用在需要数据依存关系时确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT ... FOR UPDATE方式获取排他锁
    第6楼 回到顶楼
  • cn2019
    2019-12-19 14:03 cn2019
    InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。
    第7楼 回到顶楼
  • cn2019
    2019-12-19 14:04 cn2019
    获取InonoD行锁争用情况
    可以通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    mysql> show status like 'innodb_row_lock%';
    +-------------------------------+-------+
    | Variable_name | Value |
    +-------------------------------+-------+
    | Innodb_row_lock_current_waits | 0 |
    | Innodb_row_lock_time | 0 |
    | Innodb_row_lock_time_avg | 0 |
    | Innodb_row_lock_time_max | 0 |
    | Innodb_row_lock_waits | 0 |
    +-------------------------------+-------+
    5 rows in set (0.00 sec)
    如果发现争用比较严重,如Innodb_row_lock_waits和Innodb_row_lock_time_avg的值比较高,还可以通过设置InnoDB Monitors来进一步观察发生锁冲突的表、数据行等,并分析锁争用的原因。
    第8楼 回到顶楼
  • cn2019
    2019-12-19 15:01 cn2019
    InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!
    在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。
    第9楼 回到顶楼
  • cn2019
    2019-12-19 15:03 cn2019
    对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁
    第10楼 回到顶楼
  • cn2019
    2019-12-19 15:03 cn2019
    假如emp表中只有101条记录,其empid的值分别是1,2,...,100,101,下面的SQL:
    SELECT * FROM emp WHERE empid > 100 FOR UPDATE
    第11楼 回到顶楼
  • cn2019
    2019-12-19 15:04 cn2019
    间隙锁(Next-Key锁)
    当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制不是所谓的间隙锁(Next-Key锁)。
    举例来说,假如emp表中只有101条记录,其empid的值分别是1,2,...,100,101,下面的SQL:
    SELECT * FROM emp WHERE empid > 100 FOR UPDATE
    是一个范围条件的检索,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁。
    InnoDB使用间隙锁的目的,一方面是为了防止幻读,以满足相关隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了empid大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读;另一方面,是为了满足其恢复和复制的需要。有关其恢复和复制对机制的影响,以及不同隔离级别下InnoDB使用间隙锁的情况。
    很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件
    第12楼 回到顶楼
  • cn2019
    2019-12-19 15:11 cn2019
    发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并退回,另一个事务获得锁,继续完成事务。但在涉及外部锁,或涉及锁的情况下,InnoDB并不能完全自动检测到死锁,这需要通过设置锁等待超时参数innodb_lock_wait_timeout来解决。需要说明的是,这个参数并不是只用来解决死锁问题,在并发访问比较高的情况下,如果大量事务因无法立即获取所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖垮数据库。我们通过设置合适的锁等待超时阈值,可以避免这种情况发生
    第13楼 回到顶楼
  • cn2019
    2019-12-19 16:40 cn2019
    select .... for update; 操作

    未获取到数据的时候,mysql不进行锁 (no lock)

    获取到数据的时候,进行对约束字段进行判断,存在有索引的字段则进行row lock
    否则进行 table lock
    第14楼 回到顶楼
  • cn2019
    2019-12-19 16:50 cn2019
    乐观所和悲观锁策略
    悲观锁:在读取数据时锁住那几行,其他对这几行的更新需要等到悲观锁结束时才能继续 。
    乐观所:读取数据时不锁,更新时检查是否数据已经被更新过,如果是则取消当前更新,一般在悲观锁的等待时间过长而不能接受时我们才会选择乐观锁
    第15楼 回到顶楼
  • cn2019
    2019-12-19 17:58 cn2019
    /**将此行数据进行加锁,当整个方法将事务提交后,才会解锁*/
    @Select(value = "select t from t_pub_course t where t.id = #{courseId} for update")
    第16楼 回到顶楼
登录后才能评论,请先登录注册