[toc]
Mysql中InnoDB事务
背景
python3连接mysql使用事务功能异常:
当第一条SQL成功执行,第二条SQL失败的情况下,理应两条SQL回滚,而下面代码执行时,第一条SQL成功执行并没有回滚
# -*- coding: utf-8 -*-
# @Time : 2019/11/26 14:22
# @Author : lgz
# @File : test_mysql.py
# @Software: PyCharm
def CreateDBPool(dbconfig):
import pymysql
from pymysql.cursors import DictCursor
from DBUtils import PooledDB, PersistentDB
import telnetlib
telnetlib.Telnet(dbconfig['host'], int(dbconfig['port']), timeout=5)
dbpool = PersistentDB.PersistentDB(
creator = pymysql, # 使用链接数据库的模块
maxusage = None, # 一个链接最多被使用的次数,None表示无限制
setsession = [], # 开始会话前执行的命令
ping = 0, # ping MySQL服务端,检查服务是否可用
closeable = False, # conn.close()实际上被忽略,供下次使用,直到线程关闭,自动关闭链接
threadlocal = None, # 本线程独享值的对象,用于保存链接对象
autocommit = False,
user=dbconfig['user'],
passwd= dbconfig['passwd'],
host =dbconfig['host'],
port=dbconfig['port'],
db=dbconfig['db']
)
return dbpool
dbconfig = {
'host': xxxxx,
'port': 3306,
'user': xxx,
'passwd': xxxx,
'db': xxxx,
'charset': 'utf8'
}
dbpool = CreateDBPool(dbconfig)
db=dbpool.connection()
cur=db.cursor()
try:
cur.execute("""INSERT INTO `job_summary` (`job_id`, `job_name`, `user`, `create_time`, `modify_time`, `status`)
VALUES ('job_id_ccc_1574751415', '测试任务名', '6666', '1574751416', NULL, NULL);
""")
cur.execute("""INSERT INTO `job_summary` (`job_id2`, `job_name`, `user`, `create_time`, `modify_time`, `status`)
VALUES ('123', '测试任务名', '6666', '1574751416', NULL, NULL);
""")
# cur.execute("""INSERT INTO `root_timermanage_service`.`timer_detail_jobinfo` (`id`, `uuid`, `timer_func_name`, `func_args`, `request_url`, `request_data`, `request_result`, `created_at`, `updated_at`, `timer_id`) VALUES ('1', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);""")
except Exception as e:
print(e)
db.rollback()
else:
db.commit()
finally:
cur.close() # or del cur
db.close() # or del db
原因
查看Mysql的存储引擎发现是MyISAM(InnoDB 支持事务,MyISAM 不支持事务)
MyISAM 和 InnoDB 的区别
InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;
InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;