admin

  • 标题:Google AlloyDB自持内置自然语言查询功能;达梦2024年营收为10.4亿,同比增长31%

    重要更新

    达梦发布2024年度报告,该年年度营收达10.4亿,同比增长31.49%,净利润为3.6亿。[1]

    Google AlloyDB 发布自然语言查询功能,该功能可以让开发者通过简单的配置,就可以在数据库内部实现自然语言转SQL并进行查询。[2]

    更新详情

    阿里云
    • RDS MySQL全面提升本地盘实例(含主实例和只读实例)的存储空间上限,最高支持16000 GB,满足用户存储扩容需求。[4]
    • RDS MySQL的秒级加列(Instant Add Column)通过变更数据字典的元数据来优化ADD COLUMN 操作。该功能避免了传统DDL操作对全表数据的修改或重建,实现加列操作在秒级内完成,且不受表数据量影响。[5]
    • RDS PostgreSQL ESSD云盘实例支持下载带表头信息的CSV格式备份文件,可用于数据分析或离线归档等需求。[6]
    火山云(字节)
    • veDB MySQL 支持闪回查询,通过闪回查询功能,能够直接查询过去某段时间时间内的历史数据。[7]
    • veDB MySQL 支持 RETURNING 语法,支持在执行 INSERT、REPLACE、UPDATE、DELETE 等 DML 语句时,直接返回受影响的行数据 [8]
    AWS(亚马逊云)
    • Bedrock 知识库现在支持 Aurora PostgreSQL 和 MongoDB Atlas 矢量存储的混合搜索 [18]
    • ElastiCache for Memcached 推出水平、垂直自动扩展功能[20][21]
    腾讯云
    • 数据库管理 DMC 支持了云数据库 SQL Server [22]
    • 云数据库 SQL Server 优化重启功能,支持选择重启的生效时间[23]

    参考链接

  • MySQL/InnoDB 的 隐式锁

    ·

    InnoDB 的锁容易被忽略的细节是关于“隐式锁”(即:implicit locks)的存在。表现上,有的锁是存在的,但在使用SHOW ENGINE INNODB STATUS或者performance_schema.data_locks中却查看不到。最为常见的隐式锁是在写入(INSERT)时,当前事务会持有该记录对应的锁,但是在系统中,通常是查看不到的。但,如果发生了该锁冲突(或竞争)时,系统中则可以看到此类锁信息。

    本文重现了较为常见的隐式锁场景,包括:数据写入(INSERT)时的隐式锁、根据主键操作是可能产生的二级索引隐式锁等。帮助开发者能够更系统的理解,InnoDB 的锁机制。

    写入数据产生的隐式锁

    准备数据

    DROP TABLE IF exists t1;
    
     CREATE TABLE `t1` (
      `id` int unsigned,
      `nick` varchar(32),
      `age` int,
      UNIQUE KEY `uk_n` (`nick`)
    );
    mysql> desc t1;
    +-------+--------------+------+-----+---------+
    | Field | Type         | Null | Key | Default |
    +-------+--------------+------+-----+---------+
    | id    | int unsigned | YES  |     | NULL    |
    | nick  | varchar(32)  | YES  | UNI | NULL    |
    | age   | int          | YES  |     | NULL    |
    +-------+--------------+------+-----+---------+

    mysql> INSERT INTO t1 VALUES (1, 'a' , 12),(20,'z',29);
    Query OK, 2 rows affected (0.01 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> select * from t1;
    +------+------+------+
    | id   | nick | age  |
    +------+------+------+
    |    1 | a    |   12 |
    |   20 | z    |   29 |
    +------+------+------+
    2 rows in set (0.00 sec)

    构建隐式锁

    mysql> START TRANSACTION;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> INSERT INTO t1 VALUES (8, 'h' , 32);
    Query OK, 1 row affected (0.00 sec)

    查看锁信息:

    > SELECT 
        ENGINE_TRANSACTION_ID AS TRX_ID,
        OBJECT_NAME,
        INDEX_NAME,
        LOCK_TYPE,
        LOCK_MODE,
        LOCK_STATUS,
        LOCK_DATA 
      FROM performance_schema.data_locks;
    +--------+-------------+------------+-----------+-----------+-------------+-----------+
    | TRX_ID | OBJECT_NAME | INDEX_NAME | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA |
    +--------+-------------+------------+-----------+-----------+-------------+-----------+
    |  10165 | t1          | NULL       | TABLE     | IX        | GRANTED     | NULL      |
    +--------+-------------+------------+-----------+-----------+-------------+-----------+

    可以看到,在 data_locks 表中没有任何关于事务中写入数据相关的锁。这是,因为这是一个隐式的锁,在没有任何锁竞争的情况下,系统并不会将该类型的锁展示出来(注:这可能与底层的存储和实现有关,隐式锁在实现上可能就没有“显式”的存储在锁相关的数据结构中)。

    构建锁竞争/隐式转显式

    这里通过在另一个事务中尝试并发写入一条冲突的记录,来构建锁竞争:

    mysql> START TRANSACTION;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> INSERT INTO  t1 VALUES (9,'h',17);
    ...

    该事务执行时,则会陷入锁等待。这时,再次查看锁信息如下:

    +--------+-------------+------------+-----------+---------------+-------------+---------------------+
    | TRX_ID | OBJECT_NAME | INDEX_NAME | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA           |
    +--------+-------------+------------+-----------+---------------+-------------+---------------------+
    |  10165 | t1          | NULL       | TABLE     | IX            | GRANTED     | NULL                |
    |  10168 | t1          | NULL       | TABLE     | IX            | GRANTED     | NULL                |
    |  10165 | t1          | uk_n       | RECORD    | X,REC_NOT_GAP | GRANTED     | 'h', 0x000000000214 |
    |  10168 | t1          | uk_n       | RECORD    | S             | WAITING     | 'h', 0x000000000214 |
    +--------+-------------+------------+-----------+---------------+-------------+---------------------

    这时候,可以看到事务10165,持有一个记录锁,该锁是一个排它记录锁(X,REC_NOT_GAP ),加锁对象是'h', 0x000000000214(注,这是一个唯一索引的入口,前面'h'是唯一索引值,后面的0x000000000214部分是该表的InnoDB内置rowid)。

    主键/二级索引操作相关的隐式锁

    InnoDB 的锁管理和实现确实一个超级复杂的部分(”mega-complicated“)。隐式锁的使用场景也非常多,如果对此不了解的话,那么在观察 InnoDB 的锁信息时,是会有很多的困惑的。这里再列举一类也算,较为常用的隐式锁:“主键索引/二级索引”相关的隐式说。即:

    • 当对记录进行操作时,即便是通过主键扫描,也可能对二级索引进行加锁
    • 当对记录进行操作时,即便是通过二级索引扫描,也可能对主键进行加锁

    这类场景的加锁,通常都是会存在隐式锁。

    主键操作时二级索引上的隐式锁

    在下面的测试中,我们先主键 id = 8的记录进行删除操作,然后通过系统表data_locks观察该事务是否持有二级索引相关的锁;而后,在另一个事务中,通过二级索引(nick = 'Henry')对该记录进行操作(共享读),而后再重新观察前面事务的锁状态。

    在下面的测试可以观察到,在Session B没有开始前;在 Session ADELETE语句是观测不到二级索引上的锁的;但当Session B尝试去锁定二级索引上的入口时,再次观察Session A上的锁信息,就可以看到,在Session A没有任何操作的情况下,多出了一个额外的、持有的二级索引上的锁,该锁原本是一个“隐式锁”,在发生锁竞争后,转化为一个“显式锁”。即便是在Session B因为等待操作或结束了,Session A持有的已经转化的“显式锁”也不会再回退了。详细测试如下。

    准备数据

    DROP TABLE IF exists t1;
     CREATE TABLE `t1` (
      `id` int unsigned,
      `nick` varchar(32),
      `age` int,
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_n` (`nick`)
    );
    mysql> INSERT INTO t1 VALUES (1,"Alice",12);
    mysql> INSERT INTO t1 VALUES (8,"Henry",27);
    mysql> INSERT INTO t1 VALUES (16,"Peter",15);
    mysql> show variables like '%iso%';
    +-----------------------+----------------+
    | Variable_name         | Value          |
    +-----------------------+----------------+
    | transaction_isolation | READ-COMMITTED |
    +-----------------------+----------------+

    构建隐式锁

    Session A

    mysql> START TRANSACTION;
    mysql> DELETE FROM t1 WHERE id = 8;
    
    mysql> SELECT
        ->     ENGINE_TRANSACTION_ID AS TRX_ID,
        ->     INDEX_NAME,LOCK_TYPE,
        ->     LOCK_MODE, LOCK_STATUS,
        ->     LOCK_DATA
        ->   FROM performance_schema.data_locks;
    +--------+------------+-----------+---------------+-------------+-----------+
    | TRX_ID | INDEX_NAME | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA |
    +--------+------------+-----------+---------------+-------------+-----------+
    |  10317 | NULL       | TABLE     | IX            | GRANTED     | NULL      |
    |  10317 | PRIMARY    | RECORD    | X,REC_NOT_GAP | GRANTED     | 8         |
    +--------+------------+-----------+---------------+-------------+-----------+

    Session B

    隐式锁转换为显式锁

    继续上述两个Sessions的操作:

    Session A

    Session B

    mysql> START TRANSACTION;
    mysql> SELECT * FROM t1 WHERE nick = 'Henry' FOR SHARE;
    ( Waiting )
    ...(Query Locks From performance_schema.data_locks like above)...
    +-----------------+------------+-----------+---------------+-------------+------------+
    | TRX_ID          | INDEX_NAME | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA  |
    +-----------------+------------+-----------+---------------+-------------+------------+
    |           10317 | NULL       | TABLE     | IX            | GRANTED     | NULL       |
    | 421929568337920 | NULL       | TABLE     | IS            | GRANTED     | NULL       |
    |           10317 | uk_n       | RECORD    | X,REC_NOT_GAP | GRANTED     | 'Henry', 8 |
    | 421929568337920 | uk_n       | RECORD    | S,REC_NOT_GAP | WAITING     | 'Henry', 8 |
    |           10317 | PRIMARY    | RECORD    | X,REC_NOT_GAP | GRANTED     | 8          |
    +-----------------+------------+-----------+---------------+-------------+------------+
    (... Abort last statement...)
    ERROR 1205 (HY000): Lock wait timeout exceeded; 
    try restarting transaction
    ...(Query Locks From performance_schema.data_locks like above)...
    +--------+------------+-----------+---------------+-------------+------------+
    | TRX_ID | INDEX_NAME | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA  |
    +--------+------------+-----------+---------------+-------------+------------+
    |  10317 | NULL       | TABLE     | IX            | GRANTED     | NULL       |
    |  10321 | NULL       | TABLE     | IS            | GRANTED     | NULL       |
    |  10317 | uk_n       | RECORD    | X,REC_NOT_GAP | GRANTED     | 'Henry', 8 |
    |  10317 | PRIMARY    | RECORD    | X,REC_NOT_GAP | GRANTED     | 8          |
    +--------+------------+-----------+---------------+-------------+------------+

    最后

    一些理解

    “隐式锁”可以理解为,在某些条件下,这里一定是存在“锁”的,所以,既然一定是存在的,并且这类场景可能还比较广泛,那么为了节省存储空间与操作,就省略了此类“锁”的表示。例如,通常,如果事务写入了一条数据,那么该事务一定是持有该数据的排它锁的。

    但,当真的有其他事务也尝试去获取该“隐式锁”的时候,那么为了便于进行锁检测与管理,则会重新将该锁表示出来。并且,也不再有必要重新转化为隐式锁。

    所以,如果有人问,你是否可以把当前数据库的所有的锁情况,都打印或记录下来,这是做不到的,也是没有必要的。事实上,“隐式锁”是广泛存在的,但因为通常并没有那么锁竞争,这些“隐式锁”也就一直不会被表示出来。

    一块拼图

    通常,隐式锁是可以被忽略的,如上述示例,这可能是一个没有任何竞争的锁。但,当出现对应的锁竞争时,则会变得可见。一般地,是可以不用关注隐式锁的,但,如果希望能够对 InnoDB 锁有非常系统的了解,这也是一块重要的“拼图”。

  • 标题:DBaaS服务商Tessell获 $6000万融资; OceanBase开发者大会几乎5月于广州举行

    重要更新

    多云数据库平台服务商Tessell获 $6000万 容灾。此次融资将用于进一步扩大市场覆盖,并计划推出基于 AI 驱动的对话式数据库管理服务[1]

    2025 OceanBase开发者大会将于5月17日广州举行。本届大会以「当 SQL 遇见 AI」为主题,会上,OceanBase 还将重磅发布面向 AI 时代的一体化产品矩阵,并分享 TP、AP、KV 及 AI 能力的最新实践成果。[2]

    更新详情

    阿里云
    • PolarDB 库表恢复功能支持恢复速度配置,根据所占用的IOPS越多,实际恢复速度越快。[5]
    • PolarDB 账号管理新增全局只读账号[6]
    Azure(微软云)
    • 适用于基于 vCore 的 Azure Cosmos DB for MongoDB 的 Power BI 连接器发布(预览版)[8]
    • “I/O 性能分析”支持了Azure 虚拟机上的 SQL Server[11]
    GCP(谷歌云)
    • BigQuery 数据准备功能现已正式发布 (GA),它提供 Gemini 提供的 AI 驱动的数据清理、转换和数据扩充建议。支持使用 Dataform 进行可视化数据准备流程和流程调度。[14]
    • Cloud SQL 现已支持Enterprise Plus 推荐器。根据您的应用程序工作负载和资源利用率,推荐器可以识别升级到 Cloud SQL Enterprise Plus 版本后性能提升情况 [16]
    • BigQuery ML 现已支持以下生成式 AI 函数,可让您使用 Vertex AI Gemini 模型分析文本。[28]
    • BigQuery 迁移评估现已包含对 Amazon Redshift Serverless 的支持 [34]
    • 您现在可以集成 Cloud SQL for MySQL 和 Vertex AI,这允许您使用 Vertex AI 中托管的模型和生成向量嵌入[36]
    • Spanner 现在支持以下 GoogleSQL JSON mutator 函数 [65]
    • Spanner 向量索引和近似最近邻 (ANN) 距离函数(基于 GoogleSQL 方言)现已正式发布 [70]
    • 当您创建 Cloud SQL for SQL Server 实例时,版本SQL Server 2022 Standard 现在是默认版本[71]
    • Langchain 现已支持 Spanner ANN 索引[72]
    Oracle云
    • 性能中心中的 SQL 历史记录支持数据库的SQL执行查看 [73]
    火山云(字节)
    • 数据库传输服务 DTS 支持通过物理备份迁移的方式将本地数据迁移至云数据库 SQL Server 版。[76]
    • DTS 在订阅 MySQL 类型的数据到消息队列 Kafka 版或专有网络 Kafka 进行消费时,支持自定义表投递在 Kafka 中的 Topic。[77]
    百度云
    • PegaDB支持升级小版本[79]
    • PegaDB支持实例重启
    AWS(亚马逊云)
    • RDS for Oracle 支持 BYOL 的 m6id 和 r6id 实例类[80]
    • RDS 在数据库预览环境中支持 MariaDB 11.8[81]
    • Bedrock 知识库现在支持 Aurora PostgreSQL 和 MongoDB Atlas 矢量存储的混合搜索[82]
    • 宣布推出 Amazon ElastiCache for Memcached 的水平自动扩展功能[84]
    • Aurora PostgreSQL 支持 pgvector 0.8.0[90]
    • Amazon Neptune 宣布提供 99.99% 可用性服务等级协议[96]
    腾讯云
    • TDSQL-C MySQL 、云数据库 MySQL 针对数据库审计进行了如下优化。审计日志文件列表,增加生成进度展示。[108]
    • TDSQL-C MySQL 版发布可用区迁移功能,当集群的业务区域需要迁移时,通过可用区迁移可快速实现。[110]
    • TDSQL-C MySQL 版数据库审计支持日志投递至 Ckafka 消息队列,可采集实例的数据库审计日志[111]
    • 云数据库 SQL Server 监控功能更新:新增监控指标:“闩锁等待延迟”、“每秒锁超时次数”、磁盘队列长度等[113]

    参考链接

  • 存储引擎在存储整数时,一般会使用最高位作为标志位,标记存储的整数是正数还是负数(参考),最高位也被称为“most significant bit (MSb)”。通常,最高位为1则表示正数,最高位为0,则表示负数。更进一步的,负数则会通过补码(参考:two’s complement)的方式表示。但是,InnoDB没有使用这种方法。

    InnoDB 的整数存储

    在死锁诊断时,偶然注意到,InnoDB 在存储整数时,与一般的系统是不同的。例如,int 类型存储 1 的时候,使用的表示是:0x80000001。更多的示例可以参考右图:

    整数值InnoDB 表示
    10x80000001
    -10x7fffffff
    70x80000007
    -70x7ffffff9

    可以看到,这与一般的有符号型的整数存储是相反的。即:

    • 正数表示时,最高位(MSb)为1
    • 负数表示时,最高位(MSb)为0

    关于这个问题,在 Stackoverflow上也有看到有部分用户有类似的疑问:

    本文将讨论为什么会这样。

    考虑 8-bit 场景下的

    这里来回顾一下“体系结构”中的最为基础的一些知识吧。

    整数值绝对值绝对值的二进制原码2-补码Offset binary(“移码”)
    110000-00010000-00010000-00011000-0001
    -110000-00011000-00011111-11110111-1111
    770000-01110000-01110000-01111000-0111
    -770000-01111000-01111111-100101111001

    说明:

    移码有两种计算方式,结果是等价的,即:

    • 直接将原始数据加上2(n-1),然后转化为二进制即可以
    • 将其补码,最高位进行一次翻转,即 “补码 XOR 2(n-1)

    验证存储方式

    为了确认 InnoDB 的整数处理,再MySQL 8.4.4的源码中找到如下 InnoDB 处理整型数据的代码:

      if (type == DATA_INT) {
        /* Store integer data in Innobase in a big-endian format,
        sign bit negated if the data is a signed integer. In MySQL,
        integers are stored in a little-endian format. */
    
        byte *p = buf + col_len;
    
        for (;;) {
          p--;
          *p = *mysql_data;
          if (p == buf) {
            break;
          }
          mysql_data++;
        }
    
        if (!(dtype->prtype & DATA_UNSIGNED)) {
          *buf ^= 128;
        }
    
        ptr = buf;
        buf += col_len;

    这段代码中,先将字节序做了颠倒(从最高字节位开始,逐个字节进行拷贝存储),即将 MySQL 层面的小端(little-endian)转化为了InnoDB层面的(big-endian)存储。而后,再对最高位进行了一次翻转,即这里的:*buf ^= 128操作。

    即:先将数据在MySQL层面的表示做了大小端的转化并拷贝过来,然后,将最高位进行翻转。即,先将2补码的表示模式拷贝过来,再将最高位进行翻转。

    什么要这么存储

    在 MySQL/InnoDB 官方文档或者代码中,并没有关于该实现的说明。不过这么做,有一个非常明显的好处,即所有的整数表示的大小关系,与实际存储的数据(当中无符号型对待)的大小关系是一致的。

    即,在上述的例子中:7 > 1 > -1 > -7,而对应的编码表示,也有对应的大小关系:

    0x80000007 > 0x80000001 >0x7fffffff > 0x7ffffff9

    这里对这个问题做一个简单探讨。先说结论吧,这是一种较为典型的整数编码方式:Offset binary(“移码”)。即,将需要表示的整数,加上一个数值,让所有的整数映射到自然数空间。例如,在MySQL中使用32位的int类型,需要表示的整数范围为[-231,231]。那么,实际表示时,则加上231。更为一般的,对于[-2(n-1), 2(n-1)]之间的所有整数在表示时,都加上了2(n-1)。即,建立的映射关系是:

    f(i) = i + 2(n-1)

    即对于任何要存储的整数i,实际存储时都存储上述的f(i)。而在实际运算时,则是,将补码的最高位进行一次翻转即可。

    关于补码

    例如,在 8 位二进制中,00000001 表示 +1,而 11111111 代表 -1。具体的,在表示-3 时,先取 3 的二进制 00000011,再逐位取反 11111100,最后加 1 得到 11111101,即 -3 的补码表示。这种方式让计算机能够高效地进行整数运算,是典型的正负数的方法,该方法的更多优势可以参考:two’s complement

    补充说明

    MySQL 层面的整数表示和 InnoDB 的整数存储是不同的。在“验证存储方式”小结中的代码中可以看到:

    • MySQL使用了小端(little-endian),InnoDB层面使用了大端(big-endian)存储
    • 在 MySQL 层面使用2-补码做有符号整数类型存储;而InnoDB层面使用了“移码”存储

    参考文档

  • InnoDB 的锁诊断是一个比较困难的事情。首先,锁机制是一种较为复杂的资源竞争管理机制,如果涉及的资源类型比较多,锁类型又比较多,那么锁机制就会看起来比较复杂。具体到,MySQL/InnoDB 上,确实也就非常复杂了。这里主要关注 InnoDB 层面的锁,涉及的内容则包括了记录锁(record)、间隙锁(gap)、索引缝隙锁(next-key),而为什么要加锁,则又涉及到隔离级别、MVCC的实现,而锁的实现,则又与 InnoDB 底层的数据存储结构有有一定的关系,总得来说涉及的面比较多,如果对于这些概念没有了解,则比较难理解 InnoDB 的锁机制,也就比较难去排查 InnoDB 锁出现的问题。

    另一个层面是排查手段。MySQL/InnoDB在早期的版本中,对于锁问题的排查手段是比较有限的,而且与很多的配置参数有关,所以了解这些参数,熟悉MySQL/InnoDB锁信息查看的一些方法,则是另一个需要了解的。

    所以,关于 InnoDB 锁问题的也并不是一两个话题能够说清楚的。本文可能是一个系列(给自己挖坑),一个自己学习以及锁问题排查经验的分享。

    构造主键锁竞争

    记录锁,应该是 InnoDB 锁类型中较为常见,也是在READ-COMMITTED事务级别下,比较容易遇到的死锁类型(如果有死锁的话)。这里通过观察主键死锁、唯一键死锁,初步了解 InnoDB 锁信息内容,以及结构。

    查看当前的隔离级别

    mysql> show global variables like '%iso%';
    +-----------------------+----------------+
    | Variable_name         | Value          |
    +-----------------------+----------------+
    | transaction_isolation | READ-COMMITTED |
    +-----------------------+----------------+
    1 row in set (0.01 sec)
    
    mysql> show session variables like '%iso%';
    +-----------------------+----------------+
    | Variable_name         | Value          |
    +-----------------------+----------------+
    | transaction_isolation | READ-COMMITTED |
    +-----------------------+----------------+
    1 row in set (0.00 sec)

    准备表结构

    DROP TABLE IF EXISTS t1;
    
    CREATE TABLE t1 ( 
      id int unsigned, 
      nick varchar(32),
      age int,
      primary key (id)
    )
    mysql> desc t1;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | id    | int unsigned | NO   | PRI | NULL    |       |
    | nick  | varchar(32)  | YES  |     | NULL    |       |
    | age   | int          | YES  |     | NULL    |       |
    +-------+--------------+------+-----+---------+-------+

    构建锁等待

    在两个会话中,按从上到下,执行下述的SQL:

    时间顺序Session ASession B
    1START TRANSACTION;
    2INSERT INTO t1 VALUES ( 1, "a",12 );
    3START TRANSACTION;
    4INSERT INTO t1 VALUES ( 1, "x",23 );

    这时候,Session B会陷入等待。

    观察锁信息

    通过 SHOW INNODB STATUS 观察

    此时查看 InnoDB 锁信息,则有如下数据:

    ---TRANSACTION 10094, ACTIVE 14 sec inserting
    mysql tables in use 1, locked 1
    LOCK WAIT 2 lock struct(s), heap size 1128, 1 row lock(s)
    MySQL thread id 84, OS thread handle 140453961758272, query id 9262 10.88.0.1 sysb update
    INSERT INTO t1 VALUES ( 1, "x",23 )
    ------- TRX HAS BEEN WAITING 14 SEC FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 27 page no 4 n bits 72 index PRIMARY of table `sysbenchdb`.`t1` trx id 10094 lock mode S locks rec but not gap waiting
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
     0: len 4; hex 00000001; asc     ;;
     1: len 6; hex 00000000276d; asc     'm;;
     2: len 7; hex 810000008d0110; asc        ;;
     3: len 1; hex 61; asc a;;
     4: len 4; hex 8000000c; asc     ;;
    
    ------------------
    ---TRANSACTION 10093, ACTIVE 23 sec
    2 lock struct(s), heap size 1128, 1 row lock(s), undo log entries 1
    MySQL thread id 83, OS thread handle 140454159017536, query id 9260 10.88.0.1 sysb

    SHOW ENGINE INNODB STATUS\G中仅打印了处于等待授予状态的锁信息,即这里仅打印了事务10094的等待的锁详情。

    详解锁信息

    这里详细看看其中的内容:

    RECORD LOCKS space id 27 page no 4 n bits 72 index PRIMARY of table `sysbenchdb`.`t1` trx id 10094 lock mode S locks rec but not gap waiting
    “RECORD LOCKS”这是一个记录锁
    space id 27 page no 4该记录处于物理位置,包括页面编号,以及页面所处的物理文件编号
    n bits 72该页面有72个记录对应标记位
    index PRIMARY of table sysbenchdb.t1 对应表
    trx id 10094所在的事务 ID
    lock mode S锁类型,为 S ,即共享锁
    locks rec but not gap这是一个简单记录锁,无需对记录前的“间隙”加锁
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
     0: len 4; hex 00000001; asc     ;;
     1: len 6; hex 00000000276d; asc     'm;;
     2: len 7; hex 810000008d0110; asc        ;;
     3: len 1; hex 61; asc a;;
     4: len 4; hex 8000000c; asc     ;;
    Record lock(等待的)记录锁
    heap no 2在页面中,记录以堆的方式存放,该记录的堆编号
    PHYSICAL RECORD: n_fields 5;记录共五个字段
    0: len 4; hex 00000001; asc ;;id 字段值,为1
    1: len 6; hex 00000000276d; asc 'm;;该记录的DB_TRX_ID,即为0x276d10093
    2: len 7; hex 810000008d0110; asc ;;DB_ROLL_PTR
    3: len 1; hex 61; asc a;;字段nick取值 a
    4: len 4; hex 8000000c; asc ;;字段age取值 0x8000000c,即12

    这里需要注意的是,这里一共有五个字段(n_fields 5; )。那实际这个表,只有三个字段,为什么这里会有五个字段?原因在于,InnoDB 在存储数据信息的时候,会额外的存储两个信息:DB_TRX_IDDB_ROLL_PTR。这是两个InnoDB的较为底层的概念,具体的可以参考该文档:17.3 InnoDB Multi-Versioning

    注意到,这里的 DB_TRX_ID 取值为 0x276d,转化为10进制则为:10093。即,该条记录最后一次被修改是被事务10093所修改,即上述表格中的Session A所执行的SQL所修改。

    在内置视图中查看锁信息

    mysql> SELECT
        ->     ENGINE_TRANSACTION_ID AS TRX_ID,
        ->     OBJECT_NAME,
        ->     INDEX_NAME,
        ->     LOCK_TYPE,
        ->     LOCK_MODE,
        ->     LOCK_STATUS,
        ->     LOCK_DATA
        ->   FROM performance_schema.data_locks;
    +--------+-------------+------------+-----------+---------------+-------------+-----------+
    | TRX_ID | OBJECT_NAME | INDEX_NAME | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA |
    +--------+-------------+------------+-----------+---------------+-------------+-----------+
    |  10224 | t1          | NULL       | TABLE     | IX            | GRANTED     | NULL      |
    |  10225 | t1          | NULL       | TABLE     | IX            | GRANTED     | NULL      |
    |  10224 | t1          | PRIMARY    | RECORD    | X,REC_NOT_GAP | GRANTED     | 1         |
    |  10225 | t1          | PRIMARY    | RECORD    | S,REC_NOT_GAP | WAITING     | 1         |
    +--------+-------------+------------+-----------+---------------+-------------+-----------+

    (注:这里的TRX_ID与上述不同,因为这是重新执行了上述的冲突事务)

    补充说明

    在本示例中,写入的数据仅为主键(也是一种唯一键),故无论是READ-COMMITTED、还是REPEATABLE-READ,其所需要的锁都相同的。

    相关参考资源

    1. InnoDB Locking and Transaction Model@MySQL 8.4 Reference Manual
    2. InnoDB Data Locking – Part 1 “Introduction”@MySQL Blog Archive
    3. InnoDB Data Locking – Part 2 “Locks”@MySQL Blog Archive
    4. InnoDB Data Locking – Part 2.5 “Locks” (Deeper dive)@MySQL Blog Archive
    5. InnoDB Data Locking – Part 3 “Deadlocks”@MySQL Blog Archive
    6. Understanding InnoDB Locks and Deadlocks@2015 Percona Live
    7. Introduction to Transaction Locks in InnoDB Storage Engine@2013
  • 标题: OceanBase 单机版邀测发布,资源要求2c6g;腾讯云发布双节点经济型规格; Amazon RDS支持 MySQL 9.2

    重要更新

    3月27日,OceanBase 合作伙伴大会在北京举行,单机版发布并开启邀测[1]

    更新详情

    阿里云
    • RDS SQL Server支持自定义慢日志阈值。具体的,可在参数管理页面通过设置rds_slow_log_threshold灵活调整SQL慢日志采集阈值,精准捕捉性能瓶颈相关的SQL语句,从而快速定位问题根源。[4]
    Azure(微软云)
    • Azure Database for PostgreSQL 的长期备份保留、按需备份正式 GA [5][6]
    • Azure Cosmos DB 中多区域写入帐户的时间点还原功能公测发布 [7]
    • 适用于 Azure Functions 的 Azure Database for MySQL 触发器公测发布 [8]
    GCP(谷歌云)
    火山云(字节)
    • veDB MySQL 支持参数模板的方式批量进行参数管理 [28]
    • veDB MySQL 部分参数支持与参数规格进行联动配置 [30]
    • veDB MySQL 新创建实例的默认读写终端,以及用户新建的自定义读写终端,其一致性级别的默认值将由会话一致性调整为最终一致性 [31]
    • 托管 SQL Server 支持获取连接云数据库 SQL Server 版实例的客户端 IP。[34]
    • 托管 SQL Server 物理备份方式中全量备份的基础上增加了差异备份。[37]
    • 托管 MongoDB 副本集实例,以及分片集群实例中 新增支持 oplogMinRetentionHours 参数管理 [39]
    • 托管 MongoDB 优化了 transactionLifetimeLimitSeconds 参数,将参数取值范围上限调整为 200 [40]
    AWS(亚马逊云)
    • RDS 在数据库预览环境中支持 MySQL 9.2 [42]
    • RDS for SQL Server 支持链接到 Teradata 数据库的服务器 [48]
    腾讯云
    • 云数据库 MySQL 5.7内核版本更新20250330。[58]
    • 云数据库 MySQL 全新支持双节点经济型实例。新架构提供稳定服务,满足业务所需的计算和存储需求的同时降低了使用成本,为中小型企业、个人开发者提供更加适配业务需求的数据库服务。[59]
    • 云数据库 MySQL 只读分析引擎发布了全新的问题修复版本1.2404.22.1与2.2410.4.1。[60]
    • TDSQL-C MySQL 版只读分析引擎发布了全新的问题修复版本1.2404.22.1与2.2410.4.1。[61]
    • TDSQL-C MySQL 版8.0内核版本更新3.1.15.006,提升数据库性能与稳定性。[62]

    参考链接