多个事务操作同一资源会出现的问题
- 更新丢失:A事务对数据的更新被B事务对事务的更新覆盖
- 脏读:一个事务处理过程中读取了另一个未提交的事务中的数据。比如A向B转账100,如果不加锁,A还没提交B就读到了转入100,这时A回滚,那B只能空欢喜一场。
- 不可重复读:一个事务内多次读取同一数据,由于中间被另一事务修改过,导致前后不一致。比如学生A查看自己成绩为100分,这时老师B在背后把该成绩改成50分,A第二天再查成绩发现不是number one 了。
- 幻读:第一个事务对一个表中的数据进行修改,而数据设计表中的全部数据行,这时第二个事务新增/删除一条数据,那操作第一个事务的用户发现表中还有没被修改的数据行。比如小明第一次查排名发现自己是倒数第一,刚好成绩更差的小强插班进来,小明第二次查排名时开心地发现自己不是最后一名。
读写锁
- 有两种锁:
- 排它锁即写锁,X
- 共享锁即读锁,S
- 规则:上读锁时,新的事务可以继续加读锁,但绝不允许加写锁;任意一个加写锁后,不允许其他事务加任何锁。
- 意向锁:有行级锁和表级锁,前者粒度细 IX/IS都是表锁,X/S时行锁
- 规则:
- 一个事务在某个数据行对象的S锁之前,必须先获得表的IS锁或者更强的锁
- 一个事务在获得某个数据行对象的X锁之前,必须先获得表的IX锁
- 解释:IX/IS之间都是兼容的,他们只是表示想加锁,二不是真正加锁
- 规则:
隔离级别及其实现
- 读未提交:能解决丢失更新问题。读数据时不加锁,写数据时加行级共享锁,提交时释放锁。
- 读提交:能解决脏读问题。事务读取数据时加行级共享锁,读完释放,保证读的时候不被修改。
- 可重复读(MySQL默认):解决不可重复读的问题。读时加行级共享锁,直到事务结束;更新时加行级排它锁,知道事务结束才释放。InnoDB通过MVCC实现。
- 串行化:解决幻读。读时加表级共享锁直到事务结束。写时加表级排它锁直到事务结束。
参考资料
- 《操作系统》——北大陈向群
- <a href=https://blog.csdn.net/u014634576/article/details/52600826>银行家算法Java实现</a>