MySQL锁机制
锁是计算机协调多个进程或线程并发访问某一资源的机制
例如在淘宝买商品的模型,只有一件商品时,如何解决谁买到商品的问题
这里要用到事务,先从库存表中取出物品数量,然后再插入订单,付款后插入付款表信息,
然后再更新商品数量,再这个过程中使用锁可以对有限的资源进行保护,解决隔离和并发的矛盾。
锁的分类
-
按数据操作的类型分
-
读锁
共享锁,针对同一份数据,多个读操作可以同时进行而不相互影响
-
写锁
排它锁,当前写操作未完成前,会阻断其他写锁和读锁
-
-
从对数据操作的粒度来分
-
表锁
偏读,偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率大,并发度最低。
#上锁 #lock table 锁名字 read(write) 表名字2 read(write) 其它; show open tables; #解锁 unlock tables; #exp : 读阻塞写的例子 lock table mylock read; #session2可以读mylock,session1不能修改mylock,而且session1不能读被锁表之外的其他表,sessoin2,修改mylock时导致阻塞, update mylock set name='a2' where id=1; #exp : lock table mylock write; #session1可以读、改锁定表mylock,但不可以读其他表,session2读写mylock被阻塞
MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。MyISAM的读写调度时写优先,不适合做写为主表的引擎。写锁后其他线程不能做任何操作,大量的更新会使查询很难得到锁。
#分析表锁定
show status like ‘table%’;Table_locks_immediate:产生表级锁定的次数,表示可以立即获取锁的查询次数
Table_locks_waited:出现表级锁定争用而发生的等待次数
读锁阻塞写,写锁都阻塞(不同事务间)
共享锁(S锁)又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排他锁(X锁)又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
-
行锁
偏写,偏向InnoDB存储引擎(5.5版本以后默认引擎),开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率最低。
CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
读己之所写(不同session读到数据不一样)
autocommit=0; #***** commit;
提交更新以后,其他事务(行锁)的更新才可以正常(否则阻塞)。
无索引行锁升级为表锁
-
#强制类型转换 ==>varchar 不写 ‘’ 例如:
update test_innodb_lock set a=41 where b=4000;
```
#### 间隙锁
幻读的问题存在是因为新增或者更新操作,这时如果进行范围查询的时候(加锁查询),会出现不一致的问题,这时使用不同的行锁已经没有办法满足要求,需要对一定范围内的数据进行加锁,间隙锁就是解决这类问题的。在可重复读隔离级别下,数据库是通过行锁和间隙锁共同组成的(next-key lock),来实现。
##### 间隙锁的危害
当我们用范围条件而不是相等条件检索数据时,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的引索项加锁,对于键值在条件范围内但不存在的记录,叫做"间隙",InnoDB也会对这个“间隙”加锁,这种锁机制就是间隙锁(Next-Key锁)
**造成在锁定的时候无法插入锁定值范围内的任何数据。**
```mysql
update test_innodb_lock set b='0629' where a>1 and a<6;
```
**如何锁定一行**
```mysql
#for update
select * from test where a=8 for update;
```