多个事务同时更新一行数据,此时都会加锁,然后都会排队等待,必须一个事务执行完毕了,提交了,释放了锁,才能唤醒别的事务继续执行。
那么在这多个事务运行的时候,它们加的是什么锁呢?
其实是X锁,也就是Exclude独占锁,当有一个事务加了独占锁之后,此时其它事务再要更新这行数据,都是要加独占锁的,但是只能生成独占锁在后面等待。
当有人在更新数据的时候,其它的事务可以读取这行数据吗?默认情况下需要加锁吗?不用。
因为默认情况下,有人在更新数据的时候,然后你要去读取这行数据,直接默认就是开启mvcc机制的。也就是说,此时对一行数据的读和写两个操作默认是不会加锁互斥的,因为MySQL设计mvcc机制就是为了解决这个问题,避免频繁加锁互斥。
此时你读取数据,完全可以根据你的ReadView,去在undo log版本链条里找一个你能读取的版本,完全不用去顾虑别人在不在更新。就算你真的等它更新完毕了还提交了,基于mvcc机制你也读不到它更新的值啊!因为ReadView机制是不允许的,所以你默认情况下的读,完全不需要加锁,不需要去care其它事务的更新加锁问题,直接基于mvcc机制读某个快照就可以了。
那么假设万一要是你在执行查询操作的时候,就是想要加锁呢?
MySQL首先支持一种共享锁,就是S锁,这个共享锁的语法如下:select * from table lock in share mode,你在一个查询语句后面加上lock in share mode,意思就是查询的时候对一行数据加共享锁。如果此时有别的事务在更新这行数据,已经加了独占锁了,此时你的共享锁能加吗?
当然不行了,共享锁和独占锁是互斥的!此时你这个查询就只能等着了。
那么如果你先加了共享锁,然后别人来更新要加独占锁行吗?当然不行了,此时锁是互斥的,它只能等待。
那么如果你在加共享锁的时候,别人也加共享锁呢?此时是可以的,你们俩都是可以加共享锁的,共享锁和共享锁是不会互斥的。
所以这里可以先看出一个规律,就是更新数据的时候必然加独占锁,独占锁和独占锁是互斥的,此时别人不能更新;但是此时你要查询,默认是不加锁的,走mvcc机制读快照版本,但是你查询是可以手动加共享锁的,共享锁和独占锁是互斥的,但是共享锁和共享锁是不互斥的。