简谈MySQL行锁表锁

156 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

前言

大家好,我是掘金新用户小钻风头领,今天是我正式更文的第十二天;

MySql InnoDB的行锁和表锁

InnoDB的行锁: MyISAM不支持事务,InnoDB支持事务; 表锁虽然开销小,锁表快,但高并发下性能低; 行锁虽然开销大,锁表慢,但高并发下性能高点 事务和行锁都是在确保数据准确的基础上提高高并发的能力。 innodb更适合高并发场景,同时页支持事务处理

示例说明行锁和表锁:

行锁

打开两个MySQL窗口执行同一个数据库表,两个数据库执行同一个表的数据没有问题 但是不能执行同一条数据(id作为检索条件) 劣势:开销大,加锁慢,会出现死锁; 优势:锁的粒度小,发生锁冲突的概率低,处理并发能力强

1 mysql> #Transaction-A; 
2 mysql> set autocommit = 0; #关闭自动提交事务 
3 mysql> UDPATE student SET sage = 10; WHERE sid = 1; #修改一条数据 不提交事务

7 mysql> commit; #提交修改sid=1 的事务 

4 mysql> #Transaction-B; 
5 mysql> UDPATE student SET sage = 10; WHERE sid = 2; #修改一条数据OK 此时修改没有问题 
6 mysql> UDPATE student SET sage = 100; WHERE sid = 1; #此时事务B修改sid=1的数据就会出现阻塞
8 mysql> Query OK, 1 row affected (19.09 sec) #事务A提交事务后,此时事务B 修改sid=1的数据成功;数据是事务B的修改结果 多个事务操作同一行数据时,后来的事务处于阻塞状态,这样会避免脏读等数据一致性问题, 当操作多量数据时,行锁变表锁,其他事务处于等待;

表锁

1 mysql> #Transaction-A; 

3 mysql> update student set sname='铁柱' where sage= 10 ; #执行一条SQL语句 根据非id字段作为检索 

5 mysql> commit; # 然后在提交第一次执行语句的事务 2 mysql> #Transaction-B; 

4 mysql> update student set sname='爱国' where sage = 11; #此时执行这边的同表的语句,但不是同一条数据,也会等待第一次更改的事务完成,此时 ,表锁介入 

6 mysql> Query OK, 1 row affected (11.22 sec) #提交完事务,这边的SQL语句在执行 

InnoDB和MyISAM最大的不同:
       1.InnoDB支持事务
       2.默认采用行级锁,加锁可以保持事务的一致性

Mysql事务属性
     Atomicity A 原子性; 事务开始后所有的DML操作,要么全部成功,要么全部失败,通过Undo Log来实现
     Consistency C 一致性; 事务开始前和结束后,数据库的完整性约束没有破坏
     Isolation I 隔离性; 同一时刻,只允许一个事务请求同一个数据,不同的事务之间彼此没有任何干扰,通过锁机制实现 Durability
     D 持久性; 事务提交后,事务对数据库的所有更新将被保存到数据库,不能回滚,通过Redo Log来实现 事务常见问题:
     更新丢失;事务A更新1;事务B也更新1,会发生覆盖的问题 脏读;事务A读取了事务B已经修改当尚未提交的数据,若事务B回滚数据,事务A的数据存在不一致性的问题 不可重复读;事务A第一次读取最初的数据,第二次读取事务B已经提交的修改或删除的数据。导致两次读取的数据不一致 幻读;事务A根据相同的条件第二次查询到事务B提交的新增数据,两次数据结果不一致,不符合事务的隔离性

     解决行锁变表锁
将条件字段添加索引,不使用再将其删除;
但是我们操作数据量大时使用此方法有点。。。效率太低,会出现其他事务长时间锁等待和更多的冲突问题,性能严重下降 所以Mysql会将行锁升级成表锁,实际上并没有使用索引