在进行SELECT 操做前,MyiSAM会给涉及到的表加读锁。这个时候其余Session能够正常对未加锁的表进行操做。可是对加了读锁的表,只能对其进行查询(共享锁),对其修改则会阻塞,等待至表解锁后,才会生效。高并发
Session1 | Session2 |
---|---|
给TABLE_A加读锁 | 无操做 |
能够对TABLE_A进行查询,不能对TABLE_A进行修改 | 能够对TABLE_A进行查询,不能对TABLE_A进行修改 |
查询修改 TABLE_B 报错 | 查询修改 TABLE_B正常 |
修改TABLE_A报错 | 修改TABLE_A阻塞 |
Unlock tables;解锁 | TABLE_A被修改 |
在进行写操做前,MyiSAM会给涉及到的表加写锁。这个时候其余Session能够正常对未加锁的表进行操做。可是对加了写锁的表,对其进行读或写,都会阻塞,直至写锁释放后,才会进行相应操做。post
Session1 | Session2 |
---|---|
给TABLE_A加写锁 | 无操做 |
能够对TABLE_A进行修改,不能对TABLE_A进行查询 | 不能对TABLE_A进行查询,修改 |
不能对TABLE_B进行操做 | 能够对TABLE_B进行操做 |
查询TABLE_A报错 | 查询或者修改TABLE_A阻塞 |
Unlock tables;解锁 | TABLE_A被查询出结果或被修改 |
MyiSAM的读写锁调度是写优先,这也是MyiSAM不适合做为以写为主的引擎。由于写锁后,其余线程不能进行任何操做,大量的写入操做会使得查询很可贵到锁,从而形成永久堵塞。优化
IMPORTANTspa
通俗地讲:.net
读锁就是:我要备份,后面来的先别乱动(修改)东西;线程
写锁就是:我要修改,后面来的别急,排队(无论你是要读仍是要改,都得等我此次改完)。设计
InnoDB的锁机制为行锁,行锁支持事务。code
更新丢失:多个事务同时更新同一行的数据,而且不知道其余事务的存在,致使最后有的更新失效(丢失)了。
脏读:事务在更新数据的过程当中(已经修改了数据还没有提交),去读取数据,读到了中间态的数据,这些数据不符合一致性要求,即为脏读。
不可重复读:在一次的事务操做中,对某一数据进行了两次(及以上)的读操做,此时有另外一个事务在两次读操做的中间修改了数据,形成了两次读取的数据不一样,即不能够重复读(否则数据会不同)。
幻读:在一次的事务操做中,先读取了几行数据后,另外一个事务又增长或删除了数据,在此以后,此事务又去读取数据,发现数据凭空生成或消失,跟幻觉同样,即幻读。
总结:更新丢失为多个事务几乎同时修改数据出现的问题;脏读为一个事务在修改数据,另外一个事务读取(SELECT)事务出现的问题;不可重复读为一个事务在查询数据,中间有另外一个事务修改(UPDATE)了数据的问题;幻读为一个事务在查询数据,另外一个事务在插入或删除(INSERT or DELETE)数据的问题。
已提交读与可重复读是实际开发中最常用到的两种事务隔离级别,这二者主要是经过MVCC(Multi Version Concurrency Control)对并发事务问题的解决。
Read Commited
的作法是在事务的每一条SQL语句执行前生成一个快照,此时其余并发事务去读取这个数据时,避免了脏读的出现。Repeated Read
的作法是在事务的第一次查询前生成一个快照,以后在这一次事务的读取过程当中,都去读取这一次快照,从而避免了脏读和不可重复读。总结锁与隔离级别与并发问题的关系:
在默认的隔离级别下,咱们在对某几行数据进行修改或者查询的时候,只会锁住这几行数据不被修改,从而保证避免了不可重复读的出现;而咱们即便对整张表全部行都进行操做了,那也是锁住了这张表的全部行,而不是锁住这张表,不能阻止表插入新的行,从而依然会出现幻读的状况(间隙锁+行锁的Next-Key Lock解决了此问题),而最高的隔离级别则是经过将事务串行化,咱们在执行查询事务的同时是不可能有其余事务来插入数据的,从而避免了幻读的出现。
当咱们在查询语句时,条件为范围查询时,InnoDB无论这个区间是否有数据,都会将其锁住,向这个区间的“间隙”(不存在的行)插入或删除数据都会阻塞。
Next-Key Lock = Record Lock + Gap Lock InnoDB在默认隔离级别(Repeated Read)下,使用Next-Key Lock的方案解决了幻读的问题。
即在进行范围性的SELECT时,咱们先对已经存在的Records加上Record Lock
,再对此区间的间隙加上Gap Lock
,从而解决了幻读的问题。
缘由:索引失效致使的全表扫描,使得从行锁->表锁。
select … for update 语句