--先创建表 再手动加几条数据
CREATE TABLE `account_innodb`(
`id` int(2) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`balance` int(3) DEFAULT '0',
PRIMARY KEY(`id`)
) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
- 脏读的情况(读取到其他事务未提交的数据,READ COMMIT 以上隔离级别可避免)
-- 第一个会话
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
start TRANSACTION;
UPDATE account_innodb set balance = 1000 - 100 WHERE id = 1;
-- 执行到这里开始执行第二个会话
SELECT * from account_innodb where id = 1;
ROLLBACK;
-- 第二个会话
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
start TRANSACTION;
-- 脏读 读出了 会话一中未提交的事务 影响后面的业务数据正确性
select * from account_innodb where id = 1;
UPDATE account_innodb set balance = 900+200 WHERE id = 1;
commit;
- 不可重复读(读取到其他事务已提交的数据,但是会扰乱当前事务的正确性,设置REPEATABLE READ 以上级别即可避免)
-- 第一个会话
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
start TRANSACTION;
SELECT * from account_innodb where id = 1;
-- 执行这里 执行会话二的commit 就出现不可重复度 两次读取数据不一样 导致后面的业务数据出错
SELECT * from account_innodb where id = 1;
commit;
-- 第二个会话
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
start TRANSACTION;
update account_innodb set balance = balance+300 WHERE id = 1;;
commit;
-- 第一个会话 特别注意 比如读出数据是1000然后执行第二个事务并提交 使得数据是1300 然后事务1读出数据还是是1000
-- 但是update balance=balance-100之后数据是1200 这是正确的结果(balance=1000-100)就是错误的
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
start TRANSACTION;
SELECT * from account_innodb where id = 1;
-- 执行这里 执行会话二的commit 就出现不可重复度 两次读取数据不一样
SELECT * from account_innodb where id = 1;
UPDATE account_innodb set balance = balance - 100 WHERE id = 1;;
commit;
- 幻读(一般出现在事务2插入、删除操作对事务1的受影响行数出现不正确的情况,理论上是Serializable避免,但MySQL的REPEATABLE READ也做到了)
-- 第一个会话
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
start TRANSACTION;
-- 当前读也就是加了共享读锁 (还有快照读)
SELECT * from account_innodb lock in share mode;
-- 理论上是等事务2提交了之后这里更新就会出现4条受影响的行 即出现幻读(但是mysql的rr级别并没有出现幻读 而是事务2中的update会被阻塞)
UPDATE account_innodb set balance = 1000;
commit;
-- 第二个会话
SELECT @@tx_isolation;
set SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
start TRANSACTION;
insert into account_innodb VALUES(5,'new',300);
commit;