• MySQL数据库之rowid


    MySQL数据库之rowid

    在oracle数据库中,表默认以堆表的形式存储。表中的每一行数据都有一个唯一的标识符称为rowid,rowid标识了该行在oracle数据库中的物理位置。在MySQL数据库中也有rowid的概念。但是MySQL与oracle不同的是,MySQL的InnoDB引擎默认采用索引组织表。且rowid并不能直观感受到。因此,大家可能会有以下疑惑:

    1、如何感受到rowid的存在

    2、rowid和主键有什么关系

    3、如何来理解rowid的潜在瓶颈并调试验证

    4、在主键的使用中存在哪些隐患

    索引组织表

    索引组织表用一句话来概述就是,数据即索引,索引即数据。通俗的说就是表数据本身就是一颗B+树,根据主键顺序进行排列。在InnoDB引擎中,每张表都有主键,如果没有显示的定义主键。MySQL会按照如下方式定义主键:

    1、首先判断表中是否存在唯一非空索引,如果有,则该列为主键。当表中有多个非空唯一索引,InnoDB选择建表时定义的第一个非空唯一索引为主键。

    2、如果都不满足上述条件,MySQL会自动创建一个6字节大小的指针。

    _rowid介绍

    在MySQL中存在一个隐藏列 _rowid 来标记唯一标识。但是需要注意的是 _rowid 并不是一个真实存在的列,本质是一个非空唯一列的别名。因此,在某些情况下 _rowid 是不存在的。它只存在于以下情况:

    1、当表中存在一个数字类型的单列主键时, _rowid 其实指的就是这个主键列

    2、当表中不存在主键但存在一个数字类型的非空唯一列时,  _rowid 其实指的就是这个对应的非空唯一列

    详情可以参考MySQL官方文档:

    示例:

    mysql> create table test(a int primary key,b varchar(5));
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> insert into test values(1,'a'),(2,'b'),(3,'c'),(4,'c'),(5,'d');
    Query OK, 5 rows affected (0.00 sec)
    Records: 5  Duplicates: 0  Warnings: 0
    
    mysql> select _rowid from test;
    +--------+
    | _rowid |
    +--------+
    |      1 |
    |      2 |
    |      3 |
    |      4 |
    |      5 |
    +--------+
    5 rows in set (0.00 sec)

    主键使用的隐患

    主键性能问题不是一个单一的问题,需要MySQL方向持续改造的,将技术价值和业务价值结合起来。我看到很多业务中设置了自增列,但是大多数情况下,这种自增列却没有实际的业务含义,尽管是主键列保证了ID的唯一性,但是业务开发无法直接根据主键自增列来进行查询,于是他们需要寻找新的业务属性,添加一系列的唯一性索引,非唯一性索引等等,这样一来我们坚持的规范和业务使用的方式就存在了偏差。

    从另外一个维度来说,我们对于主键的理解是有偏差的,我们不能单一的认为主键就一定是从1开始的整数类型,我们需要结合业务场景来看待,比如我们的身份证其实就是一个不错的例子,把证号分成了几个区段,偏于检索和维护;或者是外出就餐时得到的流水单号,它都有一定的业务属性在里面,对于我们去理解业务的使用是一种不错的借鉴。

    rowid的瓶颈

    我们知道rowid只有6个字节,因此最大值是2^48,所以一旦 row_id超过这个值还是会递增,这种情况下是否存在隐患。我们来测试下:

    1)、创建一张表test_inc,不包含任何索引。

    create table test_inc(id int) engine=innodb;

    2)、通过ps -ef|grep mysql得到对应的进程号,使用gdb来开始做下调试配置,切记!此处应该是自己的测试环境。

    [root@all ~]# gdb -p 2295 -ex 'p dict_sys->row_id=1' -batch
    [New LWP 3097]
    [New LWP 2332]
    [New LWP 2331]
    [New LWP 2327]
    [New LWP 2326]
    [New LWP 2325]
    [New LWP 2324]
    [New LWP 2323]
    [New LWP 2322]
    [New LWP 2321]
    [New LWP 2320]
    [New LWP 2319]
    [New LWP 2318]
    [New LWP 2317]
    [New LWP 2316]
    [New LWP 2312]
    [New LWP 2311]
    [New LWP 2310]
    [New LWP 2309]
    [New LWP 2308]
    [New LWP 2307]
    [New LWP 2306]
    [New LWP 2305]
    [New LWP 2304]
    [New LWP 2303]
    [New LWP 2302]
    [New LWP 2301]
    [Thread debugging using libthread_db enabled]
    0x0000003f290df1b3 in poll () from /lib64/libc.so.6
    $1 = 1

    3)、插入一些数据,使得rowid持续自增

    insert into test_inc values(1),(2),(3);

    4)、对rowid进行重置,调整为2^48

    [root@all ~]# gdb -p 2295 -ex 'p dict_sys->row_id=281474976710656' -batch
    。。。
    。。。
    [Thread debugging using libthread_db enabled]
    0x0000003f290df1b3 in poll () from /lib64/libc.so.6
    $1 = 281474976710656

    5)、继续写入一些数据,比如我们写入4,5,6三行数据,查询结果

    mysql> insert into test_inc values(4),(5),(6); 
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> select *from test_inc;
    +------+
    | id   |
    +------+
    |    4 |
    |    5 |
    |    6 |
    |    3 |
    +------+
    4 rows in set (0.00 sec)

    查看数据结果,发现1,2两行已经被覆盖了。由此,我们可以看到rowid自增后,还是存在使用瓶颈,当然这个概率是很低的,需要自增列的值到281万亿,这是一个相当庞大的数值了,从功能上来说,应该抛出写入重复值的错误更为合理。

    而有了主键之后,上面这个瓶颈似乎就不存在了。

  • 相关阅读:
    MSMQ简例
    C#观察者模式简例
    C#常见算法题目(面试准备)
    HttpWebRequest
    自定义Attribute简例
    .Net下的 ORM框架介紹
    for xml path的应用
    .net中日至框架log4net.dll如何使用
    动态载入.ascx用户控件
    wap 2.0 编写规范
  • 原文地址:https://www.cnblogs.com/jkin/p/14185417.html
Copyright © 2020-2023  润新知