mysql性能优化-锁

理解表锁,行锁

锁是用于管理不同事务对共享资源的并发访问

表锁与行锁的区别:

锁定粒度:表锁 > 行锁

加锁效率:表锁 > 行锁

冲突概率:表锁 > 行锁

并发性能:表锁 < 行锁

InnoDB存储引擎支持行锁和表锁(另类的行锁)

mysql Innodb锁的类型

l 共享锁(行锁):Shared Locks

l 排它锁(行锁):Exclusive Locks

l意向锁共享锁(表锁):IntentionShared Locks

l 意向锁排它锁(表锁):Intention Exclusive Locks

l 自增锁:AUTO-INC Locks

行锁的算法

l 记录锁 Record Locks

l 间隙锁 Gap Locks l 临键锁 Next-key Locks

官网地址:https://dev.mysql.com/doc/refman/5.7 /en/innodb-locking.html

共享锁(Shared Locks)VS 排它锁(Exclusive Locks)

共享锁:

又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,

都能访问到数据,但是只能读不能修改;

加锁释锁方式:

select * from users WHERE id=1 LOCK IN SHARE MODE;

commit/rollback

排他锁:

又称为写锁,简称X锁,排他锁不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁、排他锁),只有该获取了排他锁的事务是可以对数据行进行读取和修改,(其他事务要读取数据可来自于快照)

加锁释锁方式:

delete / update / insert 默认加上X锁 SELECT * FROM table_name WHERE ... FOR UPDATE

commit/rollback

innodb-行锁到底锁了什么?

InnoDB的行锁是通过给索引上的索引项加锁来实现的。

只有通过索引条件进行数据检索,InnoDB才使用行级锁,否则,InnoDB 将使用表锁(锁住索引的所有记录)

表锁:lock tables xx read/write;

意向共享锁(IS)&意向排它锁(IX)

意向共享锁(IS)

表示事务准备给数据行加入共享锁,即一个数据行加共享锁前必须先取得该表的IS锁, 意向共享锁之间是可以相互兼容的

意向排它锁(IX)

表示事务准备给数据行加入排他锁,即一个数据行加排他锁前必须先取得该表的IX锁, 意向排它锁之间是可以相互兼容的

意向锁(ISIX)InnoDB数据操作之前自动加的,不需要用户干预

意义:

当事务想去进行锁表时,可以先判断意向锁是否存在,存在时则可快速返回该表不能启用表锁

自增锁AUTO-INC Locks

针对自增列自增长的一个特殊的表级别锁

show variables like 'innodb_autoinc_lock_mode';

默认取值1,代表连续,事务未提交ID永久丢失

记录锁(Record)&间隙锁(Gap)&(临健锁Next-key)

Next-key locks:

锁住记录+区间(左开右闭)

当sql执行按照索引进行数据的检索时,查询条件为范围查找(between and、<、>等)并有数据命中则此时SQL语句加上的锁为Next-key locks,锁住索引的记录+区间(左开右闭)

Gap locks:

锁住数据不存在的区间(左开右开)

当sql执行按照索引进行数据的检索时,查询条件的数据不存在,这时SQL语句加上的锁即为 Gap locks,锁住索引不存在的区间(左开右开)

Record locks:

锁住具体的索引项

当sql执行按照唯一性(Primary key、Unique key)索引进行数据的检索时,查询条件等值匹配且查询的数据是存在的,这时SQL语句加上的锁即为记录锁Record locks,锁住具体的索引项

临健锁(next-key)

当sql执行按照索引进行数据的检索时,查询条件为范围查找(between and、<、>等)并有数据命中则此时SQL语句加上的锁为Next-key locks,锁住索引的记录+区间(左开右闭)

InnoDB的引擎会用1,4,7,10(根据索引字段的关键字去划分区间,这个例子中索引字段是id,关键字是1,4,7,10,id是不自增长的)把索引划分为5个区间,都是左开右闭区间,如果搜索过程是type=range,即通过范围查询而且走了索引,还命中了数据,会锁住命中数据的区间以及下一个区间。

为什么innodb选择临健锁作为行锁的默认算法?

是为了解决幻读的问题,因为B+树是从左到右,从小到大排列的,把命中数据的区间以及相邻区间锁住,就插不进数据了。

间隙锁(Gap)

 Gap只在RR事物隔离级别存在

Gap locks: 锁住数据不存在的区间(左开右开) 当sql执行按照索引进行数据的检索时,查询条件的数据不存在,这时SQL语句加上的锁即为 Gap locks,锁住索引不存在的区间(左开右开)

记录锁(Record)

当sql执行按照唯一性(Primary key、Unique key)索引进行数据的检索时,查询条件等值匹配且查询的数据是存在的,这时SQL语句加上的锁即为记录锁Record locks,锁住具体的索引项

如果索引不是唯一索引或主键索引,而是一个普通索引且查询条件是等值匹配,还命中了数据,这时会锁住(1,7)开区间。

利用锁怎么解决脏读

脏读的主要原因是在数据插入的时候允许其他人读取这个数据,如果在插入这条数据时加上X锁(排它锁,写锁),其他事务就读不到这条数据了,解决了脏读。

利用锁怎么解决不可重复读的问题

不可重复读是因为第一次查询没有把数据锁定,如果加上S锁(共享锁,读锁),其他事务就不能进行修改了。

利用锁怎么解决幻读的问题

幻读,一般是查询范围的时候会出现,加临键锁。

死锁

多个并发事务(2个或者以上);

每个事务都持有锁(或者是已经在等待锁);

每个事务都需要再继续持有锁;

事务之间产生加锁的循环等待,形成死锁。

死锁的避免

1)类似的业务逻辑以固定的顺序访问表和行。

2)大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。

3)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概 率。

4)降低隔离级别,如果业务允许,将隔离级别调低也是较好的选择

5)为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添 加上锁(或者说是表锁)

发布了107 篇原创文章 · 获赞 96 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/madongyu1259892936/article/details/98957014