查看 warning,可以清楚地看到提示,非事务引擎无法回滚:
SHOW WARNINGS; +---------+------+---------------------------------------------------------------+ | Level | Code | Message | +---------+------+---------------------------------------------------------------+ | Warning | 1196 | Some non-transactional changed tables couldn't be rolled back | +---------+------+---------------------------------------------------------------+我们来看下现在2张表中的数据,可以看到 t1_m 的插入确实没有回滚,这与事务逻辑的预期是不一样的。
mysql> SELECT * FROM t1_m; +------+------+ | id | name | +------+------+ | 1 | test | | 2 | test | | 3 | test | +------+------+ mysql> SELECT * FROM t1_I; +------+------+ | id | name | +------+------+ | 1 | test | | 2 | test | +------+------+当我们在非事务引擎上执行事务相关的操作的时候,MySQL 一般是不会报错的,比如在非事务引擎的操作前后用 BEGIN 和 COMMIT, 这是完全可以的,并且让我们误以为操作是有事务性的,我们在使用的时候要注意这一点。
总的来说,要遵循这样的一条原则,不要在事务中混用不同的存储引擎。
5.5 到 5.6 升级问题
5.5 升级到 5.6 的时候,我们会先建立一个5.6版本的实例,然后把数据从5.5迁移到5.6,最后把连接切到 5.6 完成升级。有时候升级会失败,这是因为5.6 GTID 的一些限制导致的。
其中有一条是关于临时表的限制,官方描述如下:
Temporary tables. CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE statements are not supported inside transactions when using GTIDs (that is, when the server was started with the --enforce-gtid-consistency option). It is possible to use these statements with GTIDs enabled, but only outside of any transaction, and only with autocommit=1.限制表明不能在事务中创建临时表,可以在事务外创建,但要求 autocommit = 1。
我们新建5.6的实例的时候,会重用 5.5 的配置,autocommit 就是其中之一,并且这个是允许用户配置的,如果用户在5.5实例上把这个值改为0,然后升级到5.6,就会出错。我们知道,创建新实例的时候,会先通过 mysql_install_db 脚本初始化数据库,这包括系统表的创建、基本数据的添加等 ,其中会用到 mysql_system_tables_data.sql 这个sql脚本,里面有:
CREATE TEMPORARY TABLE tmp_db LIKE db;CREATE TEMPORARY TABLE tmp_user LIKE user;
CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv;
这样的语句,脚本执行失败,所以mysql.db 、mysql.user 和 mysql.proxies_priv表里的初始数据就没有添加进去。
error log 中会看到这样的信息
2014-12-08 20:48:15 9264 [Warning] Bootstrap mode disables GTIDs. Bootstrap mode should only be used by mysql_install_db which initializes the MySQL data directory and creates system tables. ERROR: 1787 When @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1, the statements CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE can be executed in a non-transactional context only, and require that AUTOCOMMIT = 1. 2014-12-08 20:48:16 9264 [ERROR] Aborting我们这时如果正常启动mysqld的话,会发现默认root用户是登录不进去的,因为user表是空的,根本没有root用户,而匿名用户 @localhost 又什么也做不了。
我们用 --skip-grant-tables 启动数据库后,匿名用户登录进去,查看user表,会发现是空的。
mysql> SELECT * FROM mysql.user; Empty set (0.00 sec)因为新建的数据库不可用,所以最终导致迁移失败。
这个问题的根本原因是5.5的配置文件中 autocommit = 0 导致的,所以好的解决方法是我们在升级5.6前,把这个值设置为1,然后再升级。
MySQL· 性能优化·thread pool 原理分析大连接问题
现有mysql 处理客户端连接的方式会触发mysql 新建一个线程来处理新的连接,新建的线程会处理该连接所发送的所有 SQL 请求,即 one-thread-per-connection 的方式,其创建连接的堆栈为:
mysqld_main handle_connections_sockets create_new_thread create_thread_to_handle_connection handle_one_connection线程建立后,处理请求的堆栈如下:
0 mysql_execute_command
1 0x0000000000936f40 in mysql_parse
2 0x0000000000920664 in dispatch_command
3 0x000000000091e951 in do_command
4 0x00000000008c2cd4 in do_handle_one_connection
5 0x00000000008c2442 in handle_one_connection
6 0x0000003562e07851 in start_thread () from /lib64/libpthread.so.0
7 0x0000003562ae767d in clone () from /lib64/libc.so.6
优点及存在的问题
在连接数较小的情况下可以很快的响应客户端的请求,但当连接数非常大时会创建很多线程,这样会引起以下问题:
1. 过多线程之间的切换会加重系统的负载,造成系统资源紧张且响应不及时;
2. 频繁的进行线程的创建及销毁以及线程间同时无序的竟争系统资源加重了系统的负载。
thread_pool正是为了解决以上问题而产生的;
什么是thread_pool