切换默认shell到wsl
This commit is contained in:
@@ -1,64 +1,64 @@
|
||||
# mysql锁
|
||||
* ## msyql中锁的分类
|
||||
* 从数据库操作的类型划分,mysql中的锁可以分为读锁/共享锁和写锁/排他锁
|
||||
* 读锁(S锁,Share)
|
||||
* 写锁(X锁,Exclusive)
|
||||
* 写锁和读锁示例
|
||||
```mysql
|
||||
# 为语句加上写锁
|
||||
select * from table_name for udpate
|
||||
|
||||
# 为查询语句加上读锁
|
||||
select * from table_name lock in share mode
|
||||
# or
|
||||
select * from table_name for share(mysql 8.0新增语法)
|
||||
```
|
||||
* 在获取读锁或者写锁之后,只有当事务结束之后,获取到的读锁或者写锁才会被释放。在innodb中,for update或者for share语句只会为查询匹配的行数据上锁,并且,当事务结束或者回滚之后,会释放为数据行所加的排他锁或者共享锁
|
||||
* 在对mysql中数据进行写操作(UPDATE、INSERT、DELETE)时,会通过如下方式加锁:
|
||||
* DELETE操作:对mysql表中数据执行DELETE操作,需要为要删除数据添加排他锁(X锁)
|
||||
* UPDATE操作:对mysql表中数据执行UPDATE操作分如下情况:
|
||||
* update操作不改变记录的键值,且更新的列在更新前后占用的空间未发生变化:
|
||||
* 此时会在B+数中定位到该条记录,并且为该条记录添加X锁,在修改完成之后释放X锁
|
||||
* update操作没有修改键值,但是更新前后该条记录的某一列占用空间发生了变化:
|
||||
* 此时,会先对原先的记录加上X锁,并进行DELETE操作,并且在DELETE操作后,通过INSERT操作并添加隐式锁来插入修改后的数据
|
||||
* update操作修改了键值:
|
||||
* 同样,也会通过先DELETE再INSERT的操作来更新数据
|
||||
* INSERT操作:通过添加隐式锁的操作来保证mysql中多事务的并发安全
|
||||
* 从mysql数据库的粒度来对锁进行划分
|
||||
* 表锁:
|
||||
* 表级锁会锁住mysql中的整张表,其粒度较大,受其影响并发性能较低
|
||||
* 表级锁是mysql中最基本的加锁策略,并不依赖于存储引擎,不管是innodb还是myisam都支持表级锁
|
||||
* 表级锁的使用场景:
|
||||
* 通过的select或者update、delete、insert操作innodb并不会加表级锁,但是对于alter table、drop table这类ddl语句对表的结构进行修改时,需要对其表的元数据进行加锁(MDL),对元数据加锁的过程中,想要对该表中数据进行select、delete、update、insert的操作会被阻塞
|
||||
* 对表锁进行加锁的语句:
|
||||
```mysql
|
||||
# 对表锁进行加锁
|
||||
# 在对表进行上锁操作后,无法再去读取其他未上锁的表
|
||||
lock tables table_name read/write
|
||||
|
||||
# 对上锁的表进行释放操作
|
||||
unlock tables;
|
||||
```
|
||||
* 对于myisam存储引擎,读操作之前会为涉及到的表加上读锁,并且在读操作执行完成之后释放上锁的表;而对于写操作,myisam存储引擎会在写操作执行之前为涉及到的表加上写锁。反之,innodb存储引擎在对数据进行查找和修改时不会在表级别加锁,而是会在更细的粒度上为行数据进行加锁,以此来提高程序的并发性能。
|
||||
* 元数据锁(MDL):对于表结构的修改(DDL操作),会对其元数据锁进行加锁,而对于该表的增删改操作,则是会默认加上元数据的读锁。故而在对表结构进行修改时,想要对表中数据进行増删改操作需要获取其元数据的读锁,此时对表数据的増删改操作会被阻塞。
|
||||
* 意向锁:意向锁通常用来简化行级锁和表级锁是否兼容的判断操作。如果为一个表中某条数据加上行级锁,那么innodb存储引擎会自动的为该行记录所在的页和表加上页级和表级的意向锁,那么当接下来有事务想要对该表进行表级加锁操作时,就无需查看该表中所有数据来判断是否存在表中数据的锁和表级锁冲突。只需判断该表的意向锁和想要加上的表级锁是否冲突即可。
|
||||
* 行锁
|
||||
* 相对与表锁,行锁的粒度更小,故而其并发度更高,并发性能更好。但是行锁可能会造成死锁问题,加锁的开销也更大。
|
||||
* 是否支持行锁取决与存储引擎,比如myisam不支持行锁但是innodb却支持行锁
|
||||
* 行锁种类:
|
||||
* 记录锁:记录锁针对于单条记录,在一个事物中,如果存在update、delete等修改操作,其默认会获得想要修改的那条记录的记录锁,并且在执行修改操作之后才会被释放。若一个事务中对某条记录调用update操作,那么直到当前事务提交或者回滚前,若其他事务想要修改同一行记录,会进入阻塞状态,知道持有记录写锁的退出才能继续执行。
|
||||
* 间隙锁:间隙锁对记录的范围进行加锁。间隙锁是不冲突的,多个事务可以同时持有某一个范围的间隙锁。用间隙锁或者mvcc机制都能够解决死锁问题。但是间隙锁可能会导致死锁问题,如果多个事务各自持有自己范围的间隙锁,并同时向对方持有间隙锁的范围插入数据,此时两个事务都会等待对方释放间隙锁,在这种情况下会发生死锁问题。
|
||||
* 临键锁(next-key lock):在锁住某条记录的同时也锁定某个范围内的数据,使之无法被其他事务插入数据
|
||||
* 页锁:在页面的粒度上进行上锁
|
||||
* 在粒度上,不同层级的所的数量是有上限的,例如innodb,其优先会选用行锁来进行加锁。当行锁数量过多,占用空间超过表空间上限时,会进行锁升级的行为。行锁会升级为页面锁,此时锁的粒度会增加,锁花费的开销也会变小,但是粒度变大后并发性能也会变低。
|
||||
* 通过对待锁的方式进行划分
|
||||
* 乐观锁:乐观锁假设每次对数据进行修改时,其他事务不会访问数据,故而不会对数据正真的加锁,只是会在修改时检查数据是否被其他事务修改过。
|
||||
* 乐观锁的实现方式:
|
||||
* cas
|
||||
* 版本号机制
|
||||
* 悲观锁:
|
||||
* 悲观锁假设一个事务在对数据进行修改时,其他事务也会对数据进行修改,故而在每次修改数据时都会对要修改的数据进行加锁,悲观锁是通过mysql内部提供的锁机制来实现的
|
||||
* 通过加锁方式进行划分:
|
||||
* 隐式锁:隐式锁通常用于插入操作。在某一个事务在对所记录进行插入操作时,如果其他事务想要访问该条记录,会查看最后修改该条记录的事务id是否是活跃的事务,如果是活跃事务,那么其会帮助插入事务创建一个X锁并且让自己进入阻塞状态。
|
||||
* 隐式锁是一种延迟加锁的机制,只有当有其他事务想要访问未提交事务插入的记录时,隐式锁才会被创建。该机制能够有效减少创建锁的数量。
|
||||
# mysql锁
|
||||
* ## msyql中锁的分类
|
||||
* 从数据库操作的类型划分,mysql中的锁可以分为读锁/共享锁和写锁/排他锁
|
||||
* 读锁(S锁,Share)
|
||||
* 写锁(X锁,Exclusive)
|
||||
* 写锁和读锁示例
|
||||
```mysql
|
||||
# 为语句加上写锁
|
||||
select * from table_name for udpate
|
||||
|
||||
# 为查询语句加上读锁
|
||||
select * from table_name lock in share mode
|
||||
# or
|
||||
select * from table_name for share(mysql 8.0新增语法)
|
||||
```
|
||||
* 在获取读锁或者写锁之后,只有当事务结束之后,获取到的读锁或者写锁才会被释放。在innodb中,for update或者for share语句只会为查询匹配的行数据上锁,并且,当事务结束或者回滚之后,会释放为数据行所加的排他锁或者共享锁
|
||||
* 在对mysql中数据进行写操作(UPDATE、INSERT、DELETE)时,会通过如下方式加锁:
|
||||
* DELETE操作:对mysql表中数据执行DELETE操作,需要为要删除数据添加排他锁(X锁)
|
||||
* UPDATE操作:对mysql表中数据执行UPDATE操作分如下情况:
|
||||
* update操作不改变记录的键值,且更新的列在更新前后占用的空间未发生变化:
|
||||
* 此时会在B+数中定位到该条记录,并且为该条记录添加X锁,在修改完成之后释放X锁
|
||||
* update操作没有修改键值,但是更新前后该条记录的某一列占用空间发生了变化:
|
||||
* 此时,会先对原先的记录加上X锁,并进行DELETE操作,并且在DELETE操作后,通过INSERT操作并添加隐式锁来插入修改后的数据
|
||||
* update操作修改了键值:
|
||||
* 同样,也会通过先DELETE再INSERT的操作来更新数据
|
||||
* INSERT操作:通过添加隐式锁的操作来保证mysql中多事务的并发安全
|
||||
* 从mysql数据库的粒度来对锁进行划分
|
||||
* 表锁:
|
||||
* 表级锁会锁住mysql中的整张表,其粒度较大,受其影响并发性能较低
|
||||
* 表级锁是mysql中最基本的加锁策略,并不依赖于存储引擎,不管是innodb还是myisam都支持表级锁
|
||||
* 表级锁的使用场景:
|
||||
* 通过的select或者update、delete、insert操作innodb并不会加表级锁,但是对于alter table、drop table这类ddl语句对表的结构进行修改时,需要对其表的元数据进行加锁(MDL),对元数据加锁的过程中,想要对该表中数据进行select、delete、update、insert的操作会被阻塞
|
||||
* 对表锁进行加锁的语句:
|
||||
```mysql
|
||||
# 对表锁进行加锁
|
||||
# 在对表进行上锁操作后,无法再去读取其他未上锁的表
|
||||
lock tables table_name read/write
|
||||
|
||||
# 对上锁的表进行释放操作
|
||||
unlock tables;
|
||||
```
|
||||
* 对于myisam存储引擎,读操作之前会为涉及到的表加上读锁,并且在读操作执行完成之后释放上锁的表;而对于写操作,myisam存储引擎会在写操作执行之前为涉及到的表加上写锁。反之,innodb存储引擎在对数据进行查找和修改时不会在表级别加锁,而是会在更细的粒度上为行数据进行加锁,以此来提高程序的并发性能。
|
||||
* 元数据锁(MDL):对于表结构的修改(DDL操作),会对其元数据锁进行加锁,而对于该表的增删改操作,则是会默认加上元数据的读锁。故而在对表结构进行修改时,想要对表中数据进行増删改操作需要获取其元数据的读锁,此时对表数据的増删改操作会被阻塞。
|
||||
* 意向锁:意向锁通常用来简化行级锁和表级锁是否兼容的判断操作。如果为一个表中某条数据加上行级锁,那么innodb存储引擎会自动的为该行记录所在的页和表加上页级和表级的意向锁,那么当接下来有事务想要对该表进行表级加锁操作时,就无需查看该表中所有数据来判断是否存在表中数据的锁和表级锁冲突。只需判断该表的意向锁和想要加上的表级锁是否冲突即可。
|
||||
* 行锁
|
||||
* 相对与表锁,行锁的粒度更小,故而其并发度更高,并发性能更好。但是行锁可能会造成死锁问题,加锁的开销也更大。
|
||||
* 是否支持行锁取决与存储引擎,比如myisam不支持行锁但是innodb却支持行锁
|
||||
* 行锁种类:
|
||||
* 记录锁:记录锁针对于单条记录,在一个事物中,如果存在update、delete等修改操作,其默认会获得想要修改的那条记录的记录锁,并且在执行修改操作之后才会被释放。若一个事务中对某条记录调用update操作,那么直到当前事务提交或者回滚前,若其他事务想要修改同一行记录,会进入阻塞状态,知道持有记录写锁的退出才能继续执行。
|
||||
* 间隙锁:间隙锁对记录的范围进行加锁。间隙锁是不冲突的,多个事务可以同时持有某一个范围的间隙锁。用间隙锁或者mvcc机制都能够解决死锁问题。但是间隙锁可能会导致死锁问题,如果多个事务各自持有自己范围的间隙锁,并同时向对方持有间隙锁的范围插入数据,此时两个事务都会等待对方释放间隙锁,在这种情况下会发生死锁问题。
|
||||
* 临键锁(next-key lock):在锁住某条记录的同时也锁定某个范围内的数据,使之无法被其他事务插入数据
|
||||
* 页锁:在页面的粒度上进行上锁
|
||||
* 在粒度上,不同层级的所的数量是有上限的,例如innodb,其优先会选用行锁来进行加锁。当行锁数量过多,占用空间超过表空间上限时,会进行锁升级的行为。行锁会升级为页面锁,此时锁的粒度会增加,锁花费的开销也会变小,但是粒度变大后并发性能也会变低。
|
||||
* 通过对待锁的方式进行划分
|
||||
* 乐观锁:乐观锁假设每次对数据进行修改时,其他事务不会访问数据,故而不会对数据正真的加锁,只是会在修改时检查数据是否被其他事务修改过。
|
||||
* 乐观锁的实现方式:
|
||||
* cas
|
||||
* 版本号机制
|
||||
* 悲观锁:
|
||||
* 悲观锁假设一个事务在对数据进行修改时,其他事务也会对数据进行修改,故而在每次修改数据时都会对要修改的数据进行加锁,悲观锁是通过mysql内部提供的锁机制来实现的
|
||||
* 通过加锁方式进行划分:
|
||||
* 隐式锁:隐式锁通常用于插入操作。在某一个事务在对所记录进行插入操作时,如果其他事务想要访问该条记录,会查看最后修改该条记录的事务id是否是活跃的事务,如果是活跃事务,那么其会帮助插入事务创建一个X锁并且让自己进入阻塞状态。
|
||||
* 隐式锁是一种延迟加锁的机制,只有当有其他事务想要访问未提交事务插入的记录时,隐式锁才会被创建。该机制能够有效减少创建锁的数量。
|
||||
* 显示锁:可以通过命令查看到的锁,通常会用for update、lock in share mode 或者 update、delete操作会生成显示锁
|
||||
Reference in New Issue
Block a user