图片来自于百度图片
内容提前知
1、数据库事务
2、数据库中的锁
3、数据库事务隔离级别
主要以MySQL位例
数据库事务
要想明白数据库事务,就得明白数据库得事务与什么有关。在数据库中将单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行称之位数据库得事务。简单来讲可以理解为对某一条或者多条数据进行一系列的操作,只要一条失败,那么就全部失败。
在多线程的时候我们讲到了原子性、可见性等,在数据库一个逻辑单元要想成为事务同样需要具备四性(原子性、一致性、隔离性和持久性)。
数据库中的锁
在多线程中我们已经学过锁,主要是为了保证在多并发下数据的正确性。而数据库同样采取了锁的机制来保证高并发下数据的正确性。数据库中的锁通常分为两种:乐观锁与悲观锁。
乐观锁
所谓乐观锁就是认为在操作的时候不会有人来更新我的数据,但是在更新的时候需要判断一次此数据是否被更新,是否更新需要我们程序员自己取判断。一般来说乐观锁的实现主要分为两大类
新系统
1、版本号:在数据库新增一个version字段,每读一次version就加一次,在更新的时候,判断此version的值是否和读取的值一致。hibernate默认提供了此方法的实现;
2、时间戳:同版本号的方式,需要注意的是时间戳必须要是数据库所在服务器时间。
旧系统
1、根据表中已经存在的某一个字段来判断数据是否有更新,当然要与实际业务做好绑定;
2、判断某一条数据全字段是否做了更新。
悲观锁
所谓悲观锁就是认为我在操作数据的时候总有人来对数据进行更新,因此需要对我操作的数据加上锁。此机制是利用数据库自带锁实现。
悲观锁按照作用范围主要分为行锁和表锁,所谓行锁就是锁定一行数据,所谓表锁就是将整张表锁定。
而按照锁的功能又被分为读锁、写锁。读锁又被称为共享锁,是指当一个事务对数据加了读锁时,其余事务也只能加读锁,不能有写操作,直到第一个事务释放读锁;写锁又被称为排它锁,当一个事务对数据加了写锁,其余事务均不能加锁。
一般来说数据库默认都是使用乐观锁。在MySQL中要想实现悲观锁必须将自动提交关闭,因为mysql是更新一条便提价一次。
数据库事务隔离级别
数据库的事务隔离是通过上面锁说提到的锁来实现的,如果大家有兴趣可以去接下不同的加锁方式实现不同的隔离级别,在这里我们重点关心隔离级别以及不同隔离级别可能产生的不同结果集。
四种隔离级别
读未提交(Read Uncommitted):该隔离级别指即使一个事务的更新语句没有提交,但是别的事务可以读到这个改变,几种异常情况都可能出现。极易出错,没有安全性可言,基本不会使用。
读已提交(Read Committed):该隔离级别指一个事务只能看到其他事务的已经提交的更新,看不到未提交的更新,消除了脏读和第一类丢失更新,这是大多数数据库的默认隔离级别,如Oracle,Sqlserver。
可重复读(Repeatable Read):该隔离级别指一个事务中进行两次或多次同样的对于数据内容的查询,得到的结果是一样的,但不保证对于数据条数的查询是一样的,只要存在读改行数据就禁止写,消除了不可重复读和第二类更新丢失,这是Mysql数据库的默认隔离级别。
-串行化(Serializable):意思是说这个事务执行的时候不允许别的事务并发执行.完全串行化的读,只要存在读就禁止写,但可以同时读,消除了幻读。这是事务隔离的最高级别,虽然最安全最省心,但是效率太低,一般不会用。
四种可能发生的数据错乱现象
脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问了数据,然后使用了这个数据。
不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
可重复读:与不可重复读相反。
幻读:第一个事务对数据表里面的所有数据进行修改操作,这时第二个事务也是修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有被修改的数据行,就好戏好像产生了幻觉一样。
总结
下期预告
下期将主要分享Spring中的事务,以及Spring的事务与数据库的事务关系。
如果你对Linux、Java后端、分布式系统感兴趣,扫描上方二维码,欢迎加入我们的知识星球。
领取专属 10元无门槛券
私享最新 技术干货