代码review的时候看到同事把业务锁(insertDelete实现)和业务操作放在一个事务里。
代码结构如下:
```
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
bizLockRepoImpl.insert(biz_id,id);//其中biz_id是主键
xxxxx;
xxxxx;
xxxxx;
……………;
bizLockRepoImpl.delete(biz_id,id);//其中biz_id是主键
});
```
顿感十分奇怪,这样根据『事务隔离性』的原则,岂不是等于没有做并发控制么?于是,立马安装了个mysql进行验证。实验如下,注意时序性:
实验一:
目的:
证明,虽然第一个事务还没提交,但是如果其他事务里的sql涉及到和执行中的事务有主键冲突或者update了相同行的时候,其他的事务也是不能正常提交的。
步骤:
1. 开启一个mysql终端:
2. 开启另外一个mysql终端:
输出insert语句,就挂住了。等待了一段时间之后(一直不要去commit第一个事务),报错如上。『等锁超时』。
结论:
虽然我们知道数据库具有隔离性『定义:当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。』。数据库引擎在事务commit前,也是会进行一些保护(因为数据库引擎是怎么实现的还没有去研究,先把表象说明白)。
实验二:
目的,看看我们所理解的数据库事务的『隔离性』.
1. 客户端一:
在一个事务里insert了一条记录,在这个事务里select是可以看到的。
2. 客户端二:
3. 客户端一:
执行commit work;
4. 客户端二:
再进行select。
结论:我们看到,在事务一提交前,如果我们在其他的客户端(即其他事务里)查询是看不到事务一里还没有commit的数据的。即我们讨论的事务隔离性。
网友评论