mysql innodb事务

mysql事务

mysql事务特点:ACID

  1. Atomic:原子性,就是一堆SQL,要么一起成功,要么都别执行,不允许某个SQL成功了,某个SQL失败了,不是原子性。
  2. Consistency:一致性,这个是针对数据一致性来说的,就是一组SQL执行之前,数据必须是准确的,执行之后,数据也必须是准确的。
  3. Isolation:隔离性,这个就是说多个事务在跑的时候不能互相干扰。
  4. Durability:持久性,事务成功了,就必须永久对数据的修改是有效的。

mysql四种隔离级别

(1)读未提交,Read Uncommitted:这个很坑爹,就是说某个事务还没提交的时候,修改的数据,就让别的事务给读到了,这就恶心了,很容易导致出错的。这个也叫做脏读。

(2)读已提交,Read Committed(不可重复读):这个比上面那个稍微好一点,但是一样比较尴尬,就是说事务A在跑的时候, 先查询了一个数据是值1,然后过了段时间,事务B把那个数据给修改了一下还提交了,此时事务A再次查询这个数据就成了值2了,这是读了人家事务提交的数据啊,所以是读已提交。这个也叫做不可重复读,就是所谓的一个事务内对一个数据两次读,可能会读到不一样的值。

(3)可重复读,Read Repeatable:这个就是比上面那个再好点儿,就是说事务A在执行过程中,对某个数据的值,无论读多少次都是值1;哪怕这个过程中事务B修改了数据的值还提交了,但是事务A读到的还是自己事务开始时这个数据的值。

(4)串行化:解决幻读,不可重复读和可重复读都是针对两个事务同时对某条数据在修改,但是幻读针对的是插入,比如某个事务把所有行的某个字段都修改为了2,结果另外一个事务插入了一条数据,那个字段的值是1,然后就尴尬了。第一个事务会突然发现多出来一条数据,那个数据的字段是1。如果要解决幻读,就需要使用串行化级别的隔离级别,所有事务都串行起来,不允许多个事务并行操作。

MySQL的默认隔离级别是Read Repeatable,就是可重复读,就是说每个事务都会开启一个自己要操作的某个数据的快照,事务期间,读到的都是这个数据的快照罢了,对一个数据的多次读都是一样的。

1. 读未提交

mysql> show create table test;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                           |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+```

由于mysql默认级别为可重读我们把当前session改为读未提交,并设置binlog方式

SET session transaction isolation level read uncommitted;
SET SESSION binlog_format = 'ROW';(或者是MIXED)
-- 查询当前session事务隔离级别
show session variables like '%isolation%';
事务A 事务B
start transaction; start transaction;
select * from test;
Empty set (0.00 sec)
insert into test(name) values('张三');
select * from test;
+----+--------+
| id | name |
+----+--------+
| 1 | 张三 |
+----+--------+
commit; commit;
事务A开启事务 并查询数据 发现表中没有数据,事务B开启事务 插入一条数据 且没有commit,此时事务A再次查询表 可以查出B事务新插入的数据 这就是读未提交。

2. 读已提交(不可重复读)

隔离级别设置为读已提交

SET session transaction isolation level read committed;
事务A 事务B
start transaction; start transaction;
select * from test;
+----+------+
| id | name |
| 1 | 张三 |
insert into test(name) values('李四');
select * from test;
+----+------+
| id | name |
| 1 | 张三 |
commit;
select * from test;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
| 2 | 李四 |
+----+------+
commit;
事务A开启事务 查询数据 表中有一条数据胡=,事务B开启事务 插入一条数据 ,事务A再次查询表仍然是一条数据。 事务B提交事务,事务A查询表 此时可以查出事务B新插入的数据,并且在整个事务A中 查询结果并不相同这就造成了不可重读。                      

3. 可重复读(mysql默认隔离级别)

隔离级别设置为读已提交

SET session transaction isolation level repeatable read;
事务A 事务B
start transaction; start transaction;
select * from test where id=1;
+----+------+
| id | name |
+----+------+
| 1 | 张三 |
+----+------+
update test set name=" 王五 " where id=1;
select * from test where id=1;
+----+------+
| id | name |
| 1 | 张三 |
commit;
select * from test where id=1;
+----+------+
| id | name |
| 1 | 张三 |
commit;
select * from test where id=1;
+----+------+
| id | name |
+----+------+
| 1 | 王五 |
+----+------+
事务A 开启事务,查询一下id=1的数据.事务B,开启事务,修改id=1 name=王五.事务A查询数据,数据无变化 。事务B提交事务,事务A查询数据,数据无变化。A事务提交事务,查询id=1 此时可以看到name已经更改。在A事务中,3次查询,结果一致,可重复读。

猜你喜欢

转载自blog.csdn.net/sinat_25926481/article/details/113942237