mysql数据库的隔离性

代码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了相同行的时候,其他的事务也是不能正常提交的。

      原因:在MVCC控制中,写操作是『当前读』,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。

      步骤:

     1. 开启一个mysql终端:

    2. 开启另外一个mysql终端:

mysql> insert into biz_lock vaules(8,8,now(),now());
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

     输出insert语句,就挂住了。等待了一段时间之后(一直不要去commit第一个事务),报错如上。『等锁超时』。

     结论:

     虽然我们知道数据库具有隔离性『定义:当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。』。数据库引擎在事务commit前,也是会进行一些保护(因为数据库引擎是怎么实现的还没有去研究,先把表象说明白)。

实验二:

      目的,看看我们所理解的数据库事务的『隔离性』.

     1. 客户端一:    

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into biz_lock values(9,9,now(),now());
Query OK, 1 row affected (0.00 sec)

mysql> select * from biz_lock where biz_id = 9;
+------+--------+---------------------+---------------------+
| id   | biz_id | gmt_create          | gmt_modified        |
+------+--------+---------------------+---------------------+
| 9    | 9      | 2018-01-09 19:36:47 | 2018-01-09 19:36:47 |
+------+--------+---------------------+---------------------+
1 row in set (0.00 sec)

    在一个事务里insert了一条记录,在这个事务里select是可以看到的。

    2. 客户端二:

mysql> select * from biz_lock where biz_id = 9;
Empty set (0.00 sec)

    3. 客户端一:

mysql> commit work;
Query OK, 0 rows affected (0.00 sec)

    4. 客户端二:

mysql> select * from biz_lock where biz_id = 9;
+------+--------+---------------------+---------------------+
| id   | biz_id | gmt_create          | gmt_modified        |
+------+--------+---------------------+---------------------+
| 9    | 9      | 2018-01-09 19:36:47 | 2018-01-09 19:36:47 |
+------+--------+---------------------+---------------------+
1 row in set (0.00 sec)

    结论:我们看到,在事务一提交前,如果我们在其他的客户端(即其他事务里)查询是看不到事务一里还没有commit的数据的。即我们讨论的事务隔离性。



   



MySQL 数据库隔离级别主要用于控制事务处理的并发度和一致,主要分为四个级别: 1. **读未提交(READ UNCOMMITTED)**: 这是最宽松的隔离级别,允许读取到其他事务尚未提交的数据。这可能导致数据一致问题,如脏读、不可重复读和幻读。 2. **读已提交(READ COMMITTED)**: 只能读取到其他事务已经提交了的数据。避免了脏读,但由于更新操作可能会导致不可重复读和幻读的情况。 3. **可重复读(REPEATABLE READ)**: 保证在同一事务内的查询结果始终一致,即查询结果不会受到其他事务的影响。可以防止脏读和不可重复读,但仍然可能出现幻读情况。 4. **序列化(SERIALIZABLE)**: 此级别提供最高程度的隔离,所有的事务按照固定的顺序逐一执行,完全避免了脏读、不可重复读和幻读问题,但是它通常会影响能并限制并发能力。 为了改变 MySQL 数据库的默认隔离级别,在 SQL 查询中使用 `SET` 命令即可: ```sql SET SESSION TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]; ``` 例如,将当前会话的隔离级别设置为可重复读: ```sql SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; ``` 更改隔离级别的影响因素包括但不限于数据库配置文件中的设置(例如通过 `my.cnf` 或者 `my.ini`),以及在需要时手动调整每个会话的隔离级别。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值