数据库事务隔离级别与实现原理

事物的四大特性,即常说的ACID:

	1、原子性(Atomic):指的是事物所有的操作要么全做、要么全不做。
	2、一致性(Consistency):事物应该确认数据库从一个一致状态转变为另一个一致状态。(数据库中的数据应满足完整性约束)
	3、隔离性(Isolation):指的是多个事物并发执行的时候、一个事物的执行不应当影响到其它的事物、即事物与事物之间是隔离的。
	4、持久性(Durability):指的是一个事物一旦提交、它对数据库的修改应该永久保存在数据库中。

说完了事物、说一下事物并发引起的问题:

	1、更新丢失---即一个事物的更新覆盖了另一个事物的更新。导致另一个事物的更新丢失。
		比如、你和你妻子共同有个银行账户、里面原来有1000块钱、你这个月发工资了、把你的4300块钱
		的工资存入了银行,本来应该有5300块钱的工资。但是在这个过程中、你妻子去取钱、她想取500
		买个口红、结果取得过程中、银行的取钱系统出故障了、导致数据回滚、然后银行的账户变成了	
		1000、这个时候你存入的4300块钱就不莫得了。
	2、脏读---指的是一个事物读到了另一个事物未提交的数据。 
		还是上面的场景、当你存钱的时候、你妻子正在查询余额、这个时候你还没存成功、你妻子查询出
		来的账户余额有5300、然后存钱系统出故障了,导致存钱失败。你妻子看钱多了、打算买了1500的
		口红、但是取得时候提示余额不足。所以你晚上回去就跪搓衣板了。

	3、不可重复读 --- 在一个事物中、对同一数据进行两次读取。但是读取到的结果不一致。
		上面的场景重现、在你存钱之前、你妻子想把账户里面所有的钱取出来。但是忘了账户里面还有多
		少钱、查询了一下还有1000,这个时候你不是存钱了而是打算取100块钱买包烟。等你取完之后、
		你妻子接了个电话、聊了十几分钟、挂了电话后完了自己卡里面有多少钱了,又查了一次、这个时
		候查到了900块。但是你妻子又想起了第一次看还有1000的现在就剩900了。然后。。。。凉了
	4、幻读-----在一个事物中、一个语句查询出来的结果不一致(不可重复读的不一致、指的是数据修
	改、而幻读的不一致指的是新增或者删除)。即第一次读取到的数据相比较第二次少了几条或者多了
	几条就好像产生了幻觉一样。

下面说一说解决事物并发问题的方案、即事物隔离级别:

	1、读未提交(read-uncommitted):这种隔离级别下、会解决更新丢失的问题、出现脏读、不可重复读和幻读的问题。
	2、读已提交(read-committed):这种隔离级别下会出现不可重复读和幻读的问题。(这是Oracle的默认隔离级别)
	3、可重复读(repeatable read):这种情况下会出现幻读的问题。(这是mysql默认的隔离级别、其实mysql在这种隔离级别下解决了幻读的问题)
	4、串行化(serializable):这种隔离级别最高、也是最慢、它是以串行化的方式执行的。解决所有的并发问题。

测试用到的sql语句

由于篇幅限制、暂时就不将测试的图片贴上来了。给出一些测试中用到的dml和ddl语句。
		
查询事物隔离级别的sql语句: SELECT @@tx_isolation
设置事物隔离级别: SET GLOBAL | session TRANSACTION ISOLATION 
level [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]
例如将数据库全局的隔离级别设置为读未提交 : SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
将数据库的当前session设置为可重复读的级别:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
查询数据库的自动提交是否开启:show variables like 'autocommit'
如果开启手动将其关闭: SET autocommit = off       ps:这个只是关闭当前session的

最后的重点就是mysql是如何在RR(Repeatable Read)下解决幻读问题的

	首先、事物的并发是通过加锁的方式来解决。
	但是这种锁不是常说的读锁(共享锁)或者写锁(排他锁)。而是叫next-key锁。
	next-key锁就是行锁+gap锁(间隙锁)。
	官方给出的解释是:间隙锁是锁定索引记录之间的间隙。或锁定在第一个或最后一个索引记录之前的
	间隙。例如select * from table where id between 1 and 10 是锁定1-10的间隙。
	总结下来就是:
		首先、如果where条件全部命中、则不会加gap锁、只会加记录锁。
		如果条件全部命中或者部分命中则会加gap锁。
		当整个语句不走索引的时候、会进行锁表。   

你可能感兴趣的:(数据库)