最近在项目中发现了事务之间的死锁问题,所以研究了一下MySQL锁机制,并且延伸到了MVCC等周边知识,我只在这里介绍一下开发中可能遇到的问题,具体内容推荐阅读《高性能MySQL》。
前言:mysql有两种锁机制——读锁(共享锁)和写锁,意思就是一个进程获取读锁的话,所有进程都可以进行读,但不可以写,如果一个进程获取了写锁,那除了这个进程之外其他进程都不可以进行读写。由于myisam不存在死锁的问题也不支持事务,所以这里主要介绍关于innodb的锁机制。
1、两个进程同时访问数据库中的同一条记录,一个是读,一个是写,在mysql会怎样执行呢?
在myisam中,会先进行写锁(锁表),然后进行写操作,读操作在后面阻塞,等写操作完成释放锁,才进行读操作,为什么这样呢,因为在mysql中写操作优先级高于读操作,甚至有的时候写操作来的比读操作来得晚也会排在读操作前执行,而在innodb中则是同时进行,互相不干扰,这就是MVCC(多版本控制)的功劳。
2、在事务中的死锁?
//SQL1 start transaction; update test set name='wjw' where id=1; update test set name='wy' where id=2; commit;
//SQL2 start transaction; update test set name='wjw' where id=2; update test set name='wy' where id=1; commit;
上面两个事务,如果他们都执行完第一条sql的时候,第二个事务执行了第二条sql,但是第一个事务中已经对id=1的行进行了锁定,然后就会等待第一个事务commit,当第一个事务执行第二个sql的时候发现第二个事务已经对id=2的行进行了锁定,所以会等待第二个事务commit,结果就造成了死锁,这里有一个知识点,就是事务是一个整体,只有全执行完了才算结束,这也是为什么执行完一条sql后还是锁定行。
解决办法:死锁在很多数据库中都存在,解决办法就是避免死锁,比如上面的例子,你可以把两个事务的sql数序写成一样的,第一个更新id=1的,第二个更新id=1的。在innodb中,它会自动判断是否发生了死锁,如果发生了,它会让其中一个事务成功,另一个事务报错deadlocked
3、如果两个人同时编辑一篇文章冲突了怎么办?
当第一个人编辑完就提交了,可是第二个人不知道,他编辑完也提交了,这样就把第一个人编辑的内容覆盖了,这就引出了乐观离线锁概念,具体内容可以看我另一篇文章===>12306抢票问题
PS:表达能力有限,有任何问题,欢迎交流