验证时候采用的是MySQL数据库,
建表sql语句(含数据)
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for reader
-- ----------------------------
DROP TABLE IF EXISTS `reader`;
CREATE TABLE `reader` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`reader_name` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '读者名称',
`reader_phone` varchar(11) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '读者手机号',
`reader_ctime` int(11) DEFAULT NULL,
`reader_utime` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name_phone` (`reader_name`,`reader_phone`),
KEY `idx_name_ctime` (`reader_name`,`reader_ctime`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='读者表';
-- ----------------------------
-- Records of reader
-- ----------------------------
BEGIN;
INSERT INTO `reader` VALUES (1, 'Mary', '18932452236', NULL, NULL);
INSERT INTO `reader` VALUES (2, 'TOM', '18723421245', NULL, NULL);
INSERT INTO `reader` VALUES (3, 'John', '18823492356', NULL, NULL);
INSERT INTO `reader` VALUES (4, 'James', '15823421904', NULL, NULL);
INSERT INTO `reader` VALUES (5, 'Paul', '17723438921', NULL, NULL);
INSERT INTO `reader` VALUES (6, 'lisi', '1893423', 23435564, 12134545);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
脏读
因为MySQL默认采用的 Repeatable Read隔离级别,首先把隔离级别降到最低“set tx_isolation=read-uncommitted”。
事务A | 事务B |
---|---|
start transaction; update reader set reader_name='zs' where id=6; |
|
| select reader_name from reader where id=6; 此时发现readername是zs |
rollback。回滚 |
|
事务B读取到了事务A未提交的数据,读到了脏数据。
然后把隔离级别设置成"read-committed"或者更高。再按上面操作,会发现事务B读取的reader_name是之前的值。然后事务A进行commit之后,事务B在执行select,就会发现reader_name是新值了。因为采用的读提交,所以一个事务只能读取其他事务已经提交的数据,如果其他事务未提交数据,则读取的为原数据。
不可重复读
此时把隔离级别设置成读提交"read-committed"。
事务A | 事务B |
---|---|
start transaction; select reader_name from reader where id=6; (结果是zs) |
|
| start transaction; update reader set reader_name='ls' where id=6; commit; |
select reader_name from reader where id=6; (结果是ls) |
|
在事务A看来,在一个事务中的两次select竟然是2个不同结果,感觉不可思议。其实读取其他事务已经提交的结果也很正常。因为读取就应该读取最新数据嘛。