mysql 5.1中DDL语句对Transaction的影响
来源:互联网 发布:这个驸马有淘宝gl 编辑:程序博客网 时间:2024/04/30 11:05
这个问题是从mysqlperformance上发现的,挺有意思,分享一下。DDL语句对transaction的影响。下面贴出自己的实验过程:
mysql-5.5
session1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+----+------+
| id | name |
+----+------+
| 1 | xxx |
| 2 | xxx |
| 3 | xxx |
| 4 | xxx |
+----+------+
4 rows in set (0.00 sec)
session2:
mysql> alter table test add column pas varchar(20) ;
(下面的结果是session1 commit之后的,session1没有commit,session2一直被阻塞)
Query OK, 4 rows affected (18.55 sec)
Records: 4 Duplicates: 0 Warnings: 0
---------------------------------------------------------------------------------
下面来测试mysql5.1
mysql5.1
session1:
root@localhost test 10:17:18 >start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost test 10:17:38 >select * from test;
+----+------+
| id | name |
+----+------+
| 1 | xx |
| 2 | xx |
| 3 | xx |
| 4 | xx |
+----+------+
4 rows in set (0.00 sec)
session2:
root@localhost test 10:17:29 >alter table test add column pas varchar(20);
(session2并没有被阻塞,结果瞬间出来)
Query OK, 4 rows affected (0.12 sec)
Records: 4 Duplicates: 0 Warnings: 0
此时在session1里面再次执行命令:
session1:
root@localhost test 10:17:52 >select * from test;
Empty set (0.00 sec)
可以看出,此时得到的结果集为空
注意上面的测试是在隔离级别为 REPEATABLE-READ ,将隔离级别设置为READ-COMMITTED,再次进行测试
mysql5.1
session1:
root@localhost test 10:49:46 >set tx_isolation = 'read-committed';
Query OK, 0 rows affected (0.00 sec)
root@localhost test 10:50:13 >start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost test 10:50:19 >select * from test;
+----+------+------+
| id | name | pas |
+----+------+------+
| 1 | xx | NULL |
| 2 | xx | NULL |
| 3 | xx | NULL |
| 4 | xx | NULL |
+----+------+------+
4 rows in set (0.00 sec)
session2:
root@localhost test 10:44:07 >alter table test drop column pas;
Query OK, 4 rows affected (0.08 sec)
Records: 4 Duplicates: 0 Warnings: 0
session2不被阻塞是预期的,那么如果此时在session1再次查询呢?
session1:
root@localhost test 10:50:27 >select * from test;
+----+------+
| id | name |
+----+------+
| 1 | xx |
| 2 | xx |
| 3 | xx |
| 4 | xx |
+----+------+
4 rows in set (0.00 sec)
可以看出,session1此时能得到最新的结果,因为此时的隔离级别为READ-COMMITTED,读提交,自然能读到最新的数据。
现在来解释这些现象,在mysql 5.1里面,开启一个事务,如果对表的操作仅有读操作,那么不会对表加上meta lock(也就是锁住表的结构),所以在前面的测试中可以看到session1中开启一个事务读表,session2中可以修改表结构。如果事务里面对表有写操作,那么结果肯定是session2的DDL操作肯定会被阻塞,我已经测试过了。
那么在REPEATABLE-READ隔离级别下为什么同一个事务里面读到结果不一样?一个事务里面(这里是session1)只有读操作,那么这个表就可以在其他事务中被执行DDL操作,而当session1里面再次去读表时,发现这个表结构已经被修改了,于是只好去读副本。而mysql ALTER TABLE的操作原理是:创建一个临时表、将数据插入临时表、删掉原表、重命名临时表。那么由于REPEATABLE-READ的特性,新表里面的数据肯定是读不到的(因为事务开启时间早于新表的创建时间),所以说读到的数据也就是empty set。而你可能会问为什么不去读那个原表的数据?这是因为DDL语句是不可rollback,所以之前删除原表的操作也就不会创建回滚数据。不过幸好是这个问题在mysql 5.5里面已经修正了,因此我在用mysql 5.5做测试时也就看不到mysql 5.1里面出现的现象。
对于这个问题最需要注意的地方就是在利用mysqldump备份的时候,虽然你可能使用了参数--single-transaction,结果很有可能不是你所预期的(导出来的数据是一张空表,empty set),而另一篇文章则是因为flush tables with read lock可能会导致备份时间增长,所以要小心了。
mysql-5.5
session1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+----+------+
| id | name |
+----+------+
| 1 | xxx |
| 2 | xxx |
| 3 | xxx |
| 4 | xxx |
+----+------+
4 rows in set (0.00 sec)
session2:
mysql> alter table test add column pas varchar(20) ;
(下面的结果是session1 commit之后的,session1没有commit,session2一直被阻塞)
Query OK, 4 rows affected (18.55 sec)
Records: 4 Duplicates: 0 Warnings: 0
---------------------------------------------------------------------------------
下面来测试mysql5.1
mysql5.1
session1:
root@localhost test 10:17:18 >start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost test 10:17:38 >select * from test;
+----+------+
| id | name |
+----+------+
| 1 | xx |
| 2 | xx |
| 3 | xx |
| 4 | xx |
+----+------+
4 rows in set (0.00 sec)
session2:
root@localhost test 10:17:29 >alter table test add column pas varchar(20);
(session2并没有被阻塞,结果瞬间出来)
Query OK, 4 rows affected (0.12 sec)
Records: 4 Duplicates: 0 Warnings: 0
此时在session1里面再次执行命令:
session1:
root@localhost test 10:17:52 >select * from test;
Empty set (0.00 sec)
可以看出,此时得到的结果集为空
注意上面的测试是在隔离级别为 REPEATABLE-READ ,将隔离级别设置为READ-COMMITTED,再次进行测试
mysql5.1
session1:
root@localhost test 10:49:46 >set tx_isolation = 'read-committed';
Query OK, 0 rows affected (0.00 sec)
root@localhost test 10:50:13 >start transaction;
Query OK, 0 rows affected (0.00 sec)
root@localhost test 10:50:19 >select * from test;
+----+------+------+
| id | name | pas |
+----+------+------+
| 1 | xx | NULL |
| 2 | xx | NULL |
| 3 | xx | NULL |
| 4 | xx | NULL |
+----+------+------+
4 rows in set (0.00 sec)
session2:
root@localhost test 10:44:07 >alter table test drop column pas;
Query OK, 4 rows affected (0.08 sec)
Records: 4 Duplicates: 0 Warnings: 0
session2不被阻塞是预期的,那么如果此时在session1再次查询呢?
session1:
root@localhost test 10:50:27 >select * from test;
+----+------+
| id | name |
+----+------+
| 1 | xx |
| 2 | xx |
| 3 | xx |
| 4 | xx |
+----+------+
4 rows in set (0.00 sec)
可以看出,session1此时能得到最新的结果,因为此时的隔离级别为READ-COMMITTED,读提交,自然能读到最新的数据。
现在来解释这些现象,在mysql 5.1里面,开启一个事务,如果对表的操作仅有读操作,那么不会对表加上meta lock(也就是锁住表的结构),所以在前面的测试中可以看到session1中开启一个事务读表,session2中可以修改表结构。如果事务里面对表有写操作,那么结果肯定是session2的DDL操作肯定会被阻塞,我已经测试过了。
那么在REPEATABLE-READ隔离级别下为什么同一个事务里面读到结果不一样?一个事务里面(这里是session1)只有读操作,那么这个表就可以在其他事务中被执行DDL操作,而当session1里面再次去读表时,发现这个表结构已经被修改了,于是只好去读副本。而mysql ALTER TABLE的操作原理是:创建一个临时表、将数据插入临时表、删掉原表、重命名临时表。那么由于REPEATABLE-READ的特性,新表里面的数据肯定是读不到的(因为事务开启时间早于新表的创建时间),所以说读到的数据也就是empty set。而你可能会问为什么不去读那个原表的数据?这是因为DDL语句是不可rollback,所以之前删除原表的操作也就不会创建回滚数据。不过幸好是这个问题在mysql 5.5里面已经修正了,因此我在用mysql 5.5做测试时也就看不到mysql 5.1里面出现的现象。
对于这个问题最需要注意的地方就是在利用mysqldump备份的时候,虽然你可能使用了参数--single-transaction,结果很有可能不是你所预期的(导出来的数据是一张空表,empty set),而另一篇文章则是因为flush tables with read lock可能会导致备份时间增长,所以要小心了。
- mysql 5.1中DDL语句对Transaction的影响
- Oracle中DDL语句对事务的影响
- 从Peeked Binds看DDL和DCL语句对执行计划的影响
- SQL语句中对基本表的操作(DDL)
- mysql 常用的 ddl 语句。
- Mysql查询语句中的引号对索引的影响
- Mysql中DDL(数据定义语句)
- SQL语句对Java中ResultSet效率的影响
- 【2】mysql 数据库的DDL语句
- MySql基础的增删改 ddl语句
- MySQL备注不熟悉的DML|DDL 语句
- mysql查看创建数据表的DDL语句
- MySQL的DDL语句、DML语句与DCL语句
- mysql-影响索引的语句
- mysql优化-----ddl语句
- mysql优化-----ddl语句
- MySQL DDL语句
- MySQL DDL操作语句
- 第八周实验报告1
- http-equiv是什么意思(转载)
- 表达式语言===jsp表达式
- 右键添加UltraEdit选项
- [NOIP1999]邮票面值设计
- mysql 5.1中DDL语句对Transaction的影响
- 研究Spring MVC
- httpclient.get|post处理(连接、响应超时)
- SUN GRID ENGINE 小节
- SPOJ 11. Factorial
- Tegra3-->NVIDIA-->黄仁勋
- 解决VI打开C文件,里面关键字都不变颜色(VIM安装)
- IE8“开发人员工具”使用详解
- sed在指定行插入新行