1.  隐含的执行unlock tables

  如果在锁表期间,用start transaction命令来开始一个新事务,会造成一个隐含的unlock tables 被执行,如下所示:

会话1

会话2

SELECT * FROM country WHERE country='德国';

记录为空

SELECT * FROM country WHERE country='德国';

记录为空

--  对country表进行加 写锁

LOCK TABLE country WRITE;

-- 查询 整个表读取被阻塞

SELECT * FROM country WHERE country='德国';

-- 插入一条记录

INSERT INTO country(country, last_update) VALUES('德国',NOW());

共 1 行受到影响

country_id        country    last_update

2       中国         2018-07-03 18:06:45

7       德国         2018-07-12 17:22:08

查询等待

-- 开始一个新事务

START TRANSACTION;

会话1开始一个新事务时,表锁被释放,可以查询:

SELECT * FROM country;

country_id        country    last_update

2       中国         2018-07-03 18:06:45

7       德国         2018-07-12 17:22:08

  在同一个事务中,最好不要操作不同存储引擎的表, 因为只有commit 和rollback 只能对事务类型的表进行提交和回滚。通常 提交的事务记录会到二进制的日志中, 但如果一个事务中包含非事务类型的表,那么回滚操作也会被记录到二进制日志中,以确保非事务类型表的更新可以被复制到从slave数据库中。

2.  savepoint

  在事务中可以通过定义 savepoint,指定回滚事务的一个部分,但是不能提交提交事务的一个部分, 对于复杂的应用,可以定义多个不同的savepoint 来适应不同的条件,回滚不同的savepoint。如果定义了相同名字的savepoint,则后面定义的savepoint会覆盖之前的定义。对于不再需要使用的savepoint,可以通过release savepoint 来删除savepoint。
  下面举例回滚事务的一个部分,通过定义savepoint来指定需要回滚的事务的位置。

会话1

会话2

SELECT * FROM country WHERE country='德国';

结果为空

SELECT * FROM country WHERE country='德国';

结果为空

-- 启动一个事务 插入一条记录

START TRANSACTION ;

INSERT INTO country(country, last_update) VALUES('德国',NOW());

-- 可以查询到刚插入的记录

SELECT * FROM country WHERE country='德国';

country_id        country    last_update

12     德国         2018-07-12 18:17:12

SELECT * FROM country WHERE country='德国';

结果为空

--  定义savepoint 名为testsavepoint

SAVEPOINT savepoint_test;

-- 继续插入一条记录, 此时事务还会提交

INSERT INTO country(country, last_update) VALUES('日本',NOW());

SELECT * FROM country WHERE country='德国' or country='日本'

结果为空

SELECT * FROM country WHERE country='德国' or country='日本'

country_id        country    last_update

12     德国         2018-07-12 18:17:12

13     日本         2018-07-12 18:20:33

-- 回滚刚才的定义

ROLLBACK TO SAVEPOINT savepoint_test;

SELECT * FROM country WHERE country='德国' OR country='日本'

country_id        country    last_update

12     德国         2018-07-12 18:17:12

SELECT * FROM country WHERE country='德国' or country='日本'

结果为空

-- 提交事务

COMMIT;

SELECT * FROM country WHERE country='德国' OR country='日本'

country_id        country    last_update

12     德国         2018-07-12 18:17:12

SELECT * FROM country

country_id        country    last_update

2       中国         2018-07-03 18:06:45

12     德国         2018-07-12 18:17:12

04-14 04:08