MySQL——InnoDB锁问题(四)

一、InnoDB行锁实现方式。

     InnoDB行锁是通过给索引上的索引项来加锁实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁。InnoDB行锁分三种情形。

(1)Record lock :对索引项加锁。

(2)Grap lock:对索引项之间的”间隙”、第一条记录前的“间隙”,或者最后一条记录后的“间隙”加锁。

(3)Next-key lock:前两种的组合,对记录及其前面的间隙加锁。


InnoDB这样行锁实现的特点意味着:如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果和表锁一样。

在实际的应用中,需要特别注意行锁的这一特性,否则导致大量的锁冲突,从而影响并发性能。

下面通过例子说明情况。

a、不通过索引条件查询时,Innodb会锁定表中所有记录。

如果开始tab_no_index没有索引。

    从上面表格中可以看出,session1只给一行添加排他锁,但session2在请求其他排他锁的时,却出现了锁等待!原因就是在没有锁等待的情况下,InnoDB会给所有记录添加排他锁。如果表有索引时,InnoDB就只锁定了符合条件的行,如下图所示:

创建tab_with_index表,id字段为普通的索引。



(b)、由于MySQL的行锁是争对索引添加的锁,不是争对记录添加的锁,所以虽然是访问不同的行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。设计的使用应该特别注意这一点。

(c)、当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,无论是使用主键索引,唯一索引或者普通索引,InnoDB都会使用行锁来加锁。

(d)、即使在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL通过判断不同执行计划的代价来决定的,如果MySQL认为全表扫描效率更高,比如一些很小的表,他就不会使用索引,这种情况InnoDB会对所有的记录添加行锁。

因此在分析锁冲突时,别忘记检查sql的执行计划,以确认是否真正使用索引。下面的例子中,检索值得数据类型和索引字段不同,虽然MySQL可以进行数据类型转换,但却不会使用索引,从而导致InnoDB给索引记录添加行锁。通过explain检查两条SQL的执行计划,可以清楚看到这一点。

栗子中,tab_with_index表的name字段有索引,但是name字段是varchar类型,如果where条件中,不是和varchar类型进行比较,则会对那么进行隐式的数据类型转换,导致索引无法使用,走了全表扫描。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 确实,MySQL的varchar类型在InnoDB存储引擎中的存储结构比较复杂。在InnoDB中,每个记录都被存储为一个B+树节点,每个节点都有一个固定大小的页,通常为16KB。 当一个varchar类型的列被插入到InnoDB表中时,它会被拆分成两个部分:一个是实际的数据,另一个是长度信息。长度信息会被存储在记录头中,而实际的数据会被存储在记录的数据页中。 在InnoDB中,如果一个varchar类型的列的长度小于等于768个字节,那么它会被存储在记录的数据页中。如果一个varchar类型的列的长度超过了768个字节,那么它会被存储在单独的页中,并且在记录中只存储一个指向这个页的指针。 此外,由于InnoDB使用了行级定,每个记录都需要存储一个事务ID,用于实现MVCC(多版本并发控制)。因此,在InnoDB中,每个记录头还需要存储一个6字节的事务ID和一个2字节的回滚指针。 综上所述,当使用varchar类型时,需要注意其实际数据的长度和存储引擎的存储结构,以便更好地设计表结构和查询语句。 ### 回答2: MySQL的varchar存储结构确实是相当深奥的。在InnoDB存储引擎中,varchar类型的数据存储在表的记录中,其存储结构会影响数据写入、存储空间占用和查询性能。 首先,varchar类型的数据在记录中是以变长字符串的形式进行存储的。这意味着,varchar字段占用的存储空间与其实际存储的数据长度相关,而不是固定的。相比之下,固定长度的数据类型(如char)在存储时会占用固定的存储空间,无论实际数据的长度是多少。 其次,varchar类型的数据在记录中的存储格式是由一个表示长度的字节和真实字符串数据构成的。这个长度字段用于指示存储的实际数据的长度,使得数据库可以根据需要动态地分配存储空间,从而节省了存储空间。 此外,在InnoDB存储引擎中,varchar字段的数据存储在页内部的某个位置,而不是直接存储在页上。这是由于InnoDB采用了B+树的数据结构来组织数据,为了节省存储空间和提高数据访问效率,varchar字段的数据会被存储在叶子节点中。这样一来,在查询时可以更快地遍历和定位数据,提高查询性能。 综上所述,MySQL的varchar存储结构的深度体现在其变长存储方式、长度字段和数据存储位置等方面。了解和理解这些存储结构对于正确使用varchar类型的字段、优化存储空间和提高查询性能都是非常重要的。 ### 回答3: MySQL的varchar存储结构在InnoDB引擎中确实是一个很深入的话题。InnoDB引擎是MySQL的默认引擎,它采用了B+树索引来存储数据。在InnoDB的记录存储结构中,varchar类型字段经过了一系列处理。 首先,InnoDB将每个记录分为固定长度部分和变长长度部分。varchar字段属于变长长度部分。对于varchar字段,MySQL会额外存储一个指针,指向数据存储区域。 其次,在实际存储varchar字段值时,InnoDB会使用两种方式。对于较短的varchar字段值,会直接将其存储在记录的数据域中。这样做的好处是可以减少额外的存储开销。 而对于较长的varchar字段值,InnoDB会将其存储在一个称为“Overflow Page”的额外存储空间中。Overflow Page的指针存储在记录的数据域中。Overflow Page与主记录有一个单独的物理连接。 另外,需要注意的是,在InnoDB中,varchar字段的长度是可变的,存储的最大长度由定义时的最大长度决定。这与char字段是不同的,char字段的长度是固定的。 总之,MySQL的varchar存储结构在InnoDB引擎中是相对复杂的。它采用了不同的存储方式来处理不同长度的字段值,既保证了数据的存储效率,又满足了灵活性的要求。对于开发人员来说,了解varchar存储结构对于正确使用和优化数据库非常重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值