select version();//查看数据库版本号
show variables like ‘%engine%’;//查看数据库引擎
show global variables like ‘tx_isolation’;//查看全局隔离级别
show global VARIABLES like ‘autocommit’;//查看全局事务提交方式
set SESSION autocommit = off;//设置当前链接的事务提交方式为自动提交
show VARIABLES like ‘autocommit’;//查看当前链接下事务提交方式
MySQL 中事务开始的时间
一般我们会认为 begin/start transaction 是事务开始的时间点,也就是一旦我们执行了 start transaction,就认为事务已经开始了,其实这是错误的。事务开始的真正的时间点(LSN),是 start transaction 之后执行的第一条语句,不管是什么语句,不管成功与否。
但是如果你想要达到将 start transaction 作为事务开始的时间点,那么我们必须使用:
start transaction with consistent snapshot
它的含义是:执行 start transaction 同时建立本事务一致性读的 snapshot . 而不是等到执行第一条语句时,才开始事务,并且建立一致性读的 snapshot .
效果等价于: start transaction 之后,马上执行一条 select 语句(此时会建立一致性读的snapshot)。
快照读(一致性读):简单的select操作,原理是通过mvcc实现
例如:select * from tableName;
当前读: 原理是通过nextKey实现
insert …
update …
delete …
select * from tableName lock in shareMode;
select * from tableName for update;
举例说明:假设表t中没有数据,t中有字段id,age,name
事务A | 事务B | 说明 |
---|---|---|
start transaction with consistent snapshot | 开启事务A | |
select * from t; | 事务A读取结果是空(快照读) | |
insert into t(id,age,name) values(1,1,‘狗蛋’); | 事务B成功插入一条数据(事务提交) | |
select * from t; | 事务A读取结果是空(快照读) | |
select * from t for update; | 事务A可以读取到id为1的记录(当前读) | |
insert into t(id,age,name) values(2,2,‘钢蛋’); | 事务A执行一条id为2的插入语句 | |
select * from t; | 事务A只能读取到id为2的一条记录(快照读) | |
update t set age = 10; | 能够更新id为1,2的记录,此时会更新事务A的快照 | |
select * from t; | 事务A可以读取到id为1,2的记录(快照读) | |
select * from t; | 只能够读取到id为1的记录(快照读) | |
commit; | 事务A提交 | |
select * from t; | 能够读取到id为1,2的记录(快照读) |
ps:大家可以手动验证下上面的结论
验证方式:打开多个数据库链接,通过文章开头给出的命令行修改事务的提交方式,然后就可以写sql语句验证了。
知识扩展:
MVCC
多版本并发控制 MVCC,是行级锁的一个变种,通过保存数据在某个时间节点的快照(snapshot),类似实现了行级锁。由此不同事务对同一表,同一时刻看到的数据可能是不一样的。
实现上通过在不同的数据行后增加创建日期版本号和删除日期版本号,且版本号不断递增,进而实现了数据快照。在默认的隔离级别 REPEATABLE READ级别下,查,增,删,改操作分别是:
SELECT:
InnoDB只会检索出比当前事务版本号小的数据和当前事务自身创建的数据。
行的删除数据要么为空,要么比当前版本号大
符合以上2者的数据才会被检索出
INSERT:
InnoDB为每一行数据保存当前版本号。
DELETE:
InnoDB为每所删除的每一行的删除日期标识保存当前版本号。
UPDATE:
InnoDB为更新的每一行旧数据添加删除日期标识保存当前版本号,并且复制添加一条新数据作为修改记录此记录的新建日期为当前版本号。
操作锁
SELECT:前面已经介绍过select不同情况下加的锁。
UPDATE:写锁,会阻塞问题是其是什么颗粒度的锁?
对于之前展示的数据,UPDATE操作查询WHERE中所用的条件字段如果带索引加的是行锁或者间隙锁,否则会锁定整张表。
DELETE:写锁,同update。
INSERT:只会锁定待新建的行数据。如果UPDATE操作涉及改尚未提交的行数据,则会被阻塞。比如开启两个事务,session1先进行了INSERT数据,session2执行整表更新,此时session2会等待session1提交新建数据后,再执行更新操作,session1的INSERT阻塞了session2。但是如果session2如果更新以其他的主键值未条件,则不会受到阻塞。