mysql事务

问题

概要

  1. storage engine必须支持事务
  2. 事务根据隔离级别的不同,不同事务之间有不同的可见性
  3. begin 或者 start transaction, 显式开启事务;commit显示提交事务;rollback显式回滚事务
  4. autocommit=1时,每条sql语句会自动开启和提交事务;在显示开启事务后,autocommit被自动关闭,事务结束后,autocommit又自动恢复
  5. 也有一些操作会导致事务被隐式提交,比如DML语句,开始新的事务(将自动提交前一个事务)等
  6. 事务执行期间,会根据执行的sql语句,获取一系列锁,这些锁的获取可能会导致死锁,存储引擎也会根据不同的sql语句可能增加额外的锁

事务中可能发生的问题

  1. 脏读

    1. T1第一次查询到a=1, T2修改a=2,T1再查询到a的值就是2,这时候就说T1发生了脏读,因为读到的a的值发生了变化
    2. 一般是T1读到了T2未提交的数据更新
  2. 不可重复读
    1. T1查询到table1有1一条数据a=1,T2 set a=2, T2再次读取时发现a=2
    2. 情形和脏读有点像,但是不可重复读,读到的是其他事务已提交的数据更新
  3. 幻读
    1. T1查询到a=1, T2 insert b=2, T1 再次查询发现有两条记录a=1, b=2,此时对于T1来说,就发生了幻读
    2. 一般是说相同的sql语句,但是得到不同的结果集,可能是多了(insert)或者少了(delete)
    3. 参看https://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html

隔离级别

  1. RU Read Uncommited , 脏读
  2. RC Read Commited ,不可重复读
  3. RR Repeated Read , 幻读,通过MVVC机制,可以有效缓解幻读的问题
  4. SERIALIZATION, 事务依次顺序提交,不会发生上述的问题,但是性能低下

    参看 https://www.cnblogs.com/zhoujinyi/p/3437475.HTML

MVVC

代码梳理

// sql/sql_parse.cc:mysql_execute_command
// 事务开始
// case SQLCOM_BEGIN:
if (trans_begin(thd, lex->start_transaction_opt)) { // 释放事务锁,其他错误处理,忽略} // sql/transaction.cc
trans_begin:
if (trans_check(thd) DEBUG_RETURN(TRUE);
if (thd->in_multi_stmt_transaction_mode() ||
(thd->variables.option_bits & OPTION_TABLE_LOCK)) {
thd->server_status &= ~SERVER_STATUS_IN_TRANS;
res = test(ha_commit_trans(thd, TRUE));
}
if (res) DEBUG_RETURN(TRUE);
// 待解,啥是consistent_snapshot
if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
res = ha_start_consistent_snapshot(thd); // 事务提交
// case SQLCOM_COMMIT:
if (trans_commit(thd)) { //释放事务锁,其他错误处理,忽略} // sql/transaction.cc
trans_commit:
trans_check(thd);
res = ha_commit_trans(thd, TRUE);
# 如果res==0, 则事务提交成功
if (res)
RUN_HOOK(transaction, after_rollback, (thd, FALSE));
else
RUN_HOOK(transaction, after_commit, (thd, FALSE)); // sql/handler.cc
ha_commit_trans:
// 如果是读写事务
if (thd->mdl_context.acquire_lock(&mld_request, thd->variables.lock_wait_timeout)) {
ha_rollback_trans(thd, all
}
// 如果是非两阶段事务,则直接提交
if (trans->no_2pc || (rw_ha_count <= 1)) {
error = ha_commit_one_phase(thd, all);
goto done;
} ha_commit_one_phase:
res = commit_one_phase_2(thd, all, trans, is_real_trans); commit_one_phase_2:
// 所有参与本次事务的存储引擎
Ha_trx_info *ha_info = trans->ha_list, *ha_info_next;
if (ha_info) {
for(; ha_info; ha_info = ha_info_next) {
handlerton *ht = ha_info->ht();
if (( err = ht->commit(ht, thd, all))) {
// 存储引擎commit失败,错误处理
}
ha_info_next = ha_info->next();
// 不解,直接reset后,怎么释放ha_info
ha_info->reset();
}
}

最新文章

  1. JAVA 虚拟机钩子
  2. PHP json字符串,格式化缩进显示
  3. SQL Server Management Studio 已停止工作 异常错误
  4. debian7.8 安装 chm
  5. Gradle学习系列之八——构建多个Project
  6. show engine innodb status 详解
  7. HW4.10
  8. python迭代器Itertools
  9. vmware 挂起后不能恢复
  10. Apache 项目列表功能分类便于技术选型
  11. 求职季全攻略:优秀的UX设计师作品集该如何准备?
  12. Mysql插入中文的字段内容时乱码的解决方法
  13. 自学Zabbix3.12.3-动作Action-自动发现action配置
  14. adb命令大全
  15. node.js核心技术
  16. Mybatis之mapper.xml配置文件中的#{}和${}
  17. Geolocation API
  18. TMS320VC5509片内ADC采集
  19. word删除空白行
  20. WPF控件NumericUpDown (转)

热门文章

  1. 转:Http协议中Cookie详细介绍
  2. 第二十四章、containers容器类部件QScrollArea滚动区域详解
  3. 第6章 Python中的动态可执行方法目录
  4. 第15.4节 PyCharm程序代码检测功能介绍
  5. 对 精致码农大佬 说的 Task.Run 会存在 内存泄漏 的思考
  6. 如何实现OSM地图本地发布并自定义配图
  7. 使用 open 函数 写的代码 用户名登录
  8. STL——容器(Set &amp; multiset)的大小
  9. 黑马2020JAVA-会员版课程
  10. 七牛云上传视频(后端获取tolen)