Innodb的行级锁及何时表锁

 

大家都知道Innodb采用的是行级锁机制,因此,很多人在编写程序时往往会忽视它的表锁,从而导致系统性能低下。要不掉进Innodb行级锁的陷阱,只需简单记住“Innodb行级锁只对Where条件为主键时有效,其他非主键时全都为表锁”即可。为了更好的感知这一过程,你也可以按照下面测试步骤测试下。

 

 

测试数据:

 

CREATE TABLE `t_user` (                                                                                  

`id` int(11) NOT NULL AUTO_INCREMENT,                                                                  

`name` varchar(30) DEFAULT NULL,                                                                       

`email` varchar(100) DEFAULT NULL,                                                                     

`role` int(11) DEFAULT NULL,                                                                           

PRIMARY KEY (`id`)                                                                                     

)ENGINE=InnoDB;

 

+----+--------+------------------+------+

| id | name   | email            | role |

+----+--------+------------------+------+

|  1 | zhangs | zhangs@gmial.com |    1 | 

|  2 | lis    | lis@gmail.com    |    1 | 

|  3 | wange  | wange@gmail.com  |    2 | 

|  4 | zhaoq  | zhaoq@gmail.com  |    1 | 

|  5 | sunz   | sunz@gmail.com   |    2 | 

+----+--------+------------------+------+

 

 

测试过程:

 

linux中登录三个mysql客户端,分别为session1、session2、session3,前两个用于交替输入SQL语句观察锁的存在,后一个用于查看锁时mysql的相关参数。

 

0、session1和session2中关闭自动提交

mysql> set autocommit = off;

 

一、条件为主键:

 

同记录的修改:

 

1、session1——修改主键值为1的记录

mysql> update t_user set email=replace(email, '@', '#') where id=1;

 

2、session2——修改主键值同样为1的记录

A、mysql> update t_user set email=replace(email, '#', '@') where id=1;

输入该命令回车后,将进入等待的状态。

 

B、通过session3查看:

mysql> show status like '%lock%';

+-------------------------------+-----------+

| Variable_name                 | Value     |

+-------------------------------+-----------+

| Com_lock_tables               | 0         | 

| Com_unlock_tables             | 0         | 

| Innodb_row_lock_current_waits | 1         | 

| Innodb_row_lock_time          | 1283052   | 

| Innodb_row_lock_time_avg      | 1         | 

| Innodb_row_lock_time_max      | 51645     | 

| Innodb_row_lock_waits         | 645438    | 

| Key_blocks_not_flushed        | 2         | 

| Key_blocks_unused             | 7244      | 

| Key_blocks_used               | 8         | 

| Qcache_free_blocks            | 0         | 

| Qcache_total_blocks           | 0         | 

| Table_locks_immediate         | 136234099 | 

| Table_locks_waited            | 6645      | 

+-------------------------------+-----------+

 

C、在session1中输入提交命令。

mysql> commit;

输入commit回车后,可以看到session2中的等待结束,并打印相关提示信息,如下:

Query OK, 0 rows affected (27.04 sec)

Rows matched: 1  Changed: 0  Warnings: 0

 

从A、B、C三个步骤不难看出,主键值为1的记录处于编辑状态时,其他用户想修改该记录需要排队等待。

 

修改不同记录:

 

1、session1——修改主键值为1的记录

mysql> update t_user set email=replace(email, '@', '#') where id=1;

 

2、session2——修改主键值为2的记录

A、mysql> update t_user set email=replace(email, '#', '@') where id=2;

Query OK, 0 rows affected (0.00 sec)

Rows matched: 1  Changed: 0  Warnings: 0

未出现等待,直接显示提示信息和输入提示符。

 

B、mysql> commit;

提交后,数据被修改。

 

C、在session1中输入提交命令。

mysql> commit;

 

D、session3中查看:

mysql> select * from t_user;

+----+--------+------------------+------+

| id | name   | email            | role |

+----+--------+------------------+------+

|  1 | zhangs | zhangs#gmial.com |    1 | 

|  2 | lis    | lis#gmail.com    |    1 | 

|  3 | wange  | wange@gmail.com  |    2 | 

|  4 | zhaoq  | zhaoq@gmail.com  |    1 | 

|  5 | sunz   | sunz@gmail.com   |    2 | 

+----+--------+------------------+------+

 

 

二、条件为非主键

 

1、session1——修改role为1的记录

mysql> update t_user set email=replace(email, '@', '#') where role=1;

 

2、session2

mysql> update t_user set email=replace(email, '#', '@') where role=2;

mysql> update t_user set email=replace(email, '#', '@') where id=3;

 

当session1中以非主键为条件编辑记录时,不管执行上面的哪一条都会进入等待状态。由此可见,在条件为非主键时,innodb用的是全表锁。

 

你也可以用以下命令,查看innodb锁时的相关数据

mysql> show innodb status\G;



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值