Mysql存储引擎Innodb的读写锁、行级锁

读写锁

Mysql存储引擎Innodb在处理并发读或者写的时候,通过两种类型的锁来解决并发问题,这两种锁通常称为共享锁和排他锁,也叫读锁和写锁。

读锁是共享的,即多个客户端可以同时读取同一资源。

写锁是排他的,也就是说写锁会阻塞其他的写锁和读锁。

举个例子:

客户端A读取操作不需要等待客户端B读取完成并释放锁。但客户端A进行写操作的时候,会阻塞其他客户端的读和写操作,直到客户端A写操作完成并释放锁,其他客户端才可以进行读写。

上面说了这么多,但实际上当客户端A更新某行记录的同时,客户端B任然可读取到数据,不会被阻塞,这是为什么呢?

先来了解两个东西,Redo Log(重做日志)和Undo Log(回滚日志)

redo log通常是物理日志,记录的是数据页的物理修改,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。
undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。

如果看不懂,就这样理解:当发生写操作时,Innodb会把旧数据存储到Undo Log(回滚日志)中,新数据写到Redo Log(重做日志)中。

当客户端A更新某行记录的同时,客户端B会被写锁阻塞,这时,客户端B会去Undo Log中读取旧数据。

下面来实践下。

CREATE TABLE `test001` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` char(50) DEFAULT NULL,
  `last_name` char(50) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

INSERT INTO `test001`(`id`, `first_name`, `last_name`) VALUES (1, 'fn001', 'ln001');
INSERT INTO `test001`(`id`, `first_name`, `last_name`) VALUES (2, 'fn002', 'ln002');
INSERT INTO `test001`(`id`, `first_name`, `last_name`) VALUES (3, 'fn003', 'ln003');

在一个终端执行

BEGIN;
UPDATE test001 SET first_name='update_name' WHERE last_name='ln001';

另一个终端执行

SELECT * FROM `test001` WHERE last_name='ln001';

查询依旧可以获取数据

ps:试验完成后,记得commit或者rollback结束事物。

行级锁

Innodb使用行级锁,然而这并不意味着Innodb只会锁住被修改的行。请看下面的操作。

在一个终端连接中执行

BEGIN;
UPDATE test001 SET first_name='update_name' WHERE last_name='ln001';

在另一个终端连接中执行

BEGIN;
UPDATE test001 SET first_name='update_name2222' WHERE last_name='ln002';

 

第二条SQL被阻塞超时,即更新操作不仅仅锁住了 last_name='ln001'的行,还锁住了其他行。在这个例子中,实际上锁住了整张表。

回滚上面的事物再进行下面的操作。运行  rollback

那为什么说Innodb实现了行级锁呢?我们来给last_name行加一个索引。

再次执行刚才的语句

 

可以看到两条更新语句互不干扰,由此可知Innodb通过索引,筛选出了last_name='ln001'的数据行,然后仅对last_name='ln001'的数据行加了锁,其他数据行不会被锁住,所以此时可以更新last_name='ln002'的数据行。

没加索引前,Innodb就没法通过索引筛选出指定的数据行,只能锁住整张表了。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: innodbMySQL数据库中一种非常常用的机制,它可以实现对表中某一数据的并发操作。但是在一些特定的情况下,例如在使用大量的情况下,innodb可能会升级为表。在这种情况下,对整个表的访问就会受到限制,可能会影响数据库的性能和并发能力。如果您需要进一步了解关于innodb和表的信息,建议您查看MySQL的官方文档或者咨询相关的数据库专业人士。 ### 回答2: InnoDBMySQL数据库中一种常见的存储引擎,它支持,这意味着在事务中只定需要访问的,而不是整个表。但有时,可能会升级为表。 当一条SQL语句需要定大部分或全部的表时,InnoDB会将升级为表。这种情况下,InnoDB会自动将当前升级为表级别的,以提高性能和减少开销。表可以更快地定整个表,而不需要为每一升级为表可能发生在以下情况下: 1. 使用不可重复隔离级别的事务:当一个事务正在进操作时,如果另一个事务已经对该表进了修改操作,那么为了保证数据的一致性,InnoDB会将升级为表级。 2. 查询:当一个查询使用了FOR UPDATE或LOCK IN SHARE MODE时,InnoDB会将升级为表级,以确保查询的结果不会被其他事务修改。 3. 大事务:当一个事务涉及到大量的,或需要定多个表时,为了避免冲突和死InnoDB可能会将升级为表级。 总的来说,InnoDB升级为表级是为了保证事务的一致性和数据的完整性。虽然表级可能会降低并发性能,但可以减少冲突和死的概率。在设计数据库应用程序时,应该根据实际需求和性能需求来选择适当的策略。 ### 回答3: InnoDBMySQL的一种存储引擎,它支持和表级是指对于同一张表的不同,可以同时进取和修改操作,而表级则是指对整张表进操作时会对整张表加,其他事务无法同时进取和修改操作。 在某些情况下,InnoDB可能会升级为表级。这种情况主要包括两种情况: 1. 冲突:当多个事务同时访问同一张表的不同,并且存在冲突时,InnoDB会将升级为表级。这是为了避免冲突导致的死情况发生,通过使用表级可以减少冲突的概率。 2. 隐式升级:当某个事务执一个需要全表扫描或大范围扫描操作时,InnoDB会自动将升级为表级。这是为了减少InnoDB资源占用和提高性能,因为在全表扫描或大范围扫描时,涉及的数较多,可能需要占用较多的内存资源。 升级为表的情况是自动发生的,并且开发者无法手动干预或控制。但是,表级的使用可能会对并发性能产生一定的影响。因此,为了避免升级为表级的情况发生,我们可以优化事务的操作,尽量减少冲突的可能性,使用合适的索引来减少全表扫描或大范围扫描操作的发生。 总而言之,InnoDB可以在一定程度上提高并发性能,但在特定情况下会升级为表级。了解这些情况并采取优化措施可以更有效地利用资源,提高系统的并发性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值