共享锁(读锁)
如果事务对数据A添加共享锁后,其他事务只能对A添加共享锁不可以添加排它锁,他可以被多线程共同读取,但无法区修改添加删除数据,只可以被读。
排它锁(写锁)
排他锁又叫做写锁,独占锁,当事务T对数据A添加排它锁后,该事物只允许读取A和修改,其他的事务都不可以在对数据A添加锁,直到事务提交完成后。他可以保证其他事务不能读取该数据和写数据。
互斥锁
其实概念和排他锁差不多,这里可以参考
互斥锁和读写锁的区别
,互斥锁只允许一个线程访问近来,过程中其他线程必须等待。
悲观锁
悲观锁顾名思义,就是很悲观,当我们要操作数据的时候,会很悲观的想象可能会有其他线程会修改当前数据,所以每次操作前都会加锁,synchronized就是悲观锁。
乐观锁
就是很乐观,每次拿数据的时候认为其他人不会修改,所以不会上锁,但是拿的时候会判断其他线程是否更新过这个数据,可以使用原子引用,版本号去进行控制。乐观锁适用于读多写少的场景。这种锁可以提高吞吐量因为这样就不用线程排队了。数据库中write——condition就是这种机制还有cas。
行级锁
他通常是用于mysql数据库中,锁表中的某一行,他的开销非常大,他会减少数据库的操作冲突。加锁粒度最小。开销大加锁慢,会出现死锁
表级锁
表级锁是锁定粒度最大的锁,对整张表加锁它实现简单,资源消耗最少,被大部分mysql引擎支持。mylsam和innodb都支持表锁。表级锁分为共享锁和排他锁。发生锁冲突概率最高。
页级锁
页级锁是所粒度基于行和表中间的锁。
事务中包含的问题
脏读
脏读就是读到了无用的数据,意思就是读到了事务还没有提交的数据。
脏读又称无效数据读出(读出了脏数据)。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了某个表中的一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因回滚(Rollback)了,那么事务T2读取的数据就是脏的(无效的)。
解决办法:把数据库的事务隔离级别调整到READ_COMMITTED(读提交/不可重复读)
不可重复读
在事务中,两次查询相同的数据,返回的不同的结果,造成的原因是另一个事务修改了该数据,
解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ(可重复读)
幻读
当一个事务删除所有数据后,另一个事务恰好又添加一条数据,这种类似幻觉一样的叫做幻觉
解决办法:把数据库的事务隔离级别调整到SERIALIZABLE_READ(序列化执行),或者数据库使用者自己进行加锁来保证。
数据库默认隔离级别为repeatable-read。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
读未提交:意思就是其他事务更改数据后,本事务也可以读到,容易造成脏读。
读已提交:只能读到已提交的数据。具体可以参考
事务理解