事务管理读写锁特性演示代码实现相关问题咨询
事务锁三类核心特性多会话演示
本演示基于MySQL InnoDB引擎默认的REPEATABLE READ隔离级别实现,用到的事务核心操作包括COMMIT(事务提交)、ROLLBACK(事务回滚),如需设置事务还原点可使用SAVEPOINT <还原点名称>语法,回滚到指定还原点使用ROLLBACK TO <还原点名称>即可。
首先提前准备测试表和测试数据:
CREATE DATABASE IF NOT EXISTS tx_test; USE tx_test; CREATE TABLE IF NOT EXISTS user ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, balance INT NOT NULL ); INSERT INTO user(name, balance) VALUES ('张三', 1000), ('李四', 2000);
特性a:读操作不会锁定其他读操作
需开启2个独立数据库会话分步执行:
- 会话1开启事务,执行读操作,暂不提交
-- 会话1执行 START TRANSACTION; SELECT * FROM user WHERE id = 1;
- 会话2开启事务,执行同一条读操作
-- 会话2执行 START TRANSACTION; SELECT * FROM user WHERE id = 1;
执行结果:两个会话都能立刻拿到查询结果,无任何阻塞,验证读操作之间不会互相加锁。
底层逻辑:InnoDB的一致性非锁定读通过MVCC多版本并发控制实现,普通读操作无需加锁即可获取数据。
特性b:写操作不会锁定读操作
需开启2个独立数据库会话分步执行:
- 会话1开启事务,执行写操作,暂不提交
-- 会话1执行 START TRANSACTION; UPDATE user SET balance = balance - 100 WHERE id = 1;
- 会话2开启事务,读取同一条数据
-- 会话2执行 START TRANSACTION; SELECT * FROM user WHERE id = 1;
执行结果:会话2可以立刻拿到查询结果,不会被会话1的写操作阻塞,拿到的是写操作之前的历史版本数据。
补充说明:如果使用READ COMMITTED隔离级别,会话1提交后会话2再读会拿到最新值;REPEATABLE READ级别下会话2同一事务内多次读取结果始终一致。
特性c:写操作会锁定其他写操作
需开启2个独立数据库会话分步执行:
- 会话1开启事务,执行写操作,暂不提交
-- 会话1执行 START TRANSACTION; UPDATE user SET balance = balance - 100 WHERE id = 1;
- 会话2开启事务,执行同一条数据的写操作
-- 会话2执行 START TRANSACTION; UPDATE user SET balance = balance + 100 WHERE id = 1;
执行结果:会话2的写操作会进入阻塞状态,直到会话1执行
COMMIT或者ROLLBACK释放行锁之后,会话2的操作才会继续执行。如果阻塞超过InnoDB默认锁等待时间(50秒)会抛出锁等待超时错误。
内容的提问来源于stack exchange,提问作者AlbertAlex
相关产品推荐
相关产品推荐

