目录
事务
概念:数据库操作的最小单位。
MySQL默认一句sql语句就是一个事务。用户可以手动定义好几个sql语句为一个事务。这些操作要么全部执行,要么全不执行。
事务的四大特性:
1、原子性: 事务不可再分 (类似的还有数据库表属性)。
2、一致性:操作前后数据库总量不变。
3、隔离性:一个事务提交前,对于其他事物是不可见的。
4、永久性:提交到数据库中的数据会永久保存
前提要求:
1、存储引擎为:innoDB
在使用事务前,必须保证表的存储引擎是:innoDB类型。MySQL数据库中表的存储引擎默认是innoDB。
表的存储引擎提供表的存储机制,不同表的存储引擎提供不同机制。
查看MySQL数据库所支持的表的存储引擎
show engines;
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| CSV | YES | CSV storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.03 sec)
常用:
innoDB:支持事务——保证数据的一致性和完整性,使用户的操作更加安全。
MyISAM: 不支持事务,访问速度快。如果你想查询\插入为主可以使用MyISAM
show create table students; # 查看students 的存储引擎。
开启事务:
1、begin
被事务所封装的语句
2、start transaction
被事务锁封装的语句。
开启事务后,变更的数据会保存到本地缓存文件中,而不维护到物理表中。
只有执行commit() \ 或者rollback() ,才会将修改后的数据提交到物理表中。
MySQL默认采用自动提交:
在,autocommit模式下,如果没有显示的开启一个事务,每条sql语句会被当做一份事务执行提交的操作。当autocommit=0(非自交模式),需要执显示行到commit/rallback才能结束该事务。
设置非自动提交:
set autocommit=0;
改回自动提交: set autocommit=1 or 关闭终端,重新打开。且不同终端之间设置autocommit互不影响。
查看当前的提交状态:
select @@autocommit;
只要自己开了一个事务:系统就不会帮你提交。
即使 autocommit=1 也需要自己提交。
获取游标。会给我们开一个事务 ,所以必须自己提交。
eg: 非自动提交情况下,插入一个数据:
insert into students values (3,"王皓");
当前终端操作结果:
mysql> insert into students values (3,"王皓");
Query OK, 1 row affected (0.00 sec)mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
| 3 | 王皓 |
+----+--------+
2 rows in set (0.00 sec)
新终端操作结果:
mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
+----+--------+
1 row in set (0.00 sec)
说明数据只存在本地缓存,并没有维护到物理表中。也证明了事务的隔离性:在数据提交前对于另一个事务是不可见的。执行本地回滚后查询结果:
mysql> rollback;
Query OK, 0 rows affected (0.04 sec)mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
+----+--------+
1 row in set (0.00 sec)本地存储的王皓被丢弃。
此时执行commit后的查询结果:
本地和新终端都如下所示:
mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
+----+--------+
1 row in set (0.00 sec)重新插入一个数据,并手动提交。
当前终端:
mysql> insert into students values(4,'张帅');
Query OK, 1 row affected (0.00 sec)mysql> commit;
Query OK, 0 rows affected (0.04 sec)mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
| 4 | 张帅 |
+----+--------+
2 rows in set (0.00 sec)新终端:
mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
+----+--------+
1 row in set (0.00 sec)mysql> select * from students;
+----+--------+
| id | name |
+----+--------+
| 2 | 张力 |
| 4 | 张帅 |
+----+--------+
2 rows in set (0.00 sec)
索引:
什么是索引?
通俗理解索引: 书前的目录,通过目录可快速定位书的内容
应用场景: 数据量大时,想快速查找数据。
索引:提高查询速度、需增加开销。每增加一个索引,相当于创建了一个索引文件,会增加磁盘的空间的开销。
索引的使用:
1、查看索引
show index from 表名;
数据库会默认给主键添加一个索引。
2、创建索引 (索引和外键的添加都用alter 因为这都是对表结构的修改,索引也叫做“键”,是一种特殊的文件。)
alter table 表名 add index 索引名(列名);
mysql> show index from students;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+-为name属性添加索引:
1、创表的时候增加索引:
create table stuents1 (id int unsigned not null primary key auto_imcrement,name varchat(20) not null,index(name));
alter table students add index (name) 我这里没有指定索引名,默认为字段名“name”
mysql> alter table students add index (name);
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> show index from students;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
| students | 1 | name | 1 | name | A | 2 | NULL | NULL | | BTREE | | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
索引的删除:
alter table 表名 drop index 索引名
mysql> mysql> alter tadents drop index name;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0mysql> show index from students;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| students | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)创建索引检测:
开启时间检测:set profiling = 1;
联合索引:复合索引 ,即一个索引覆盖表中两个或多个字段,一般用在多个字段一起查询。
create table students
(id int not null primary key auto_increment,name varchat(20) not null ,age tinyint nor null
);
alter table students add index (name,age) 不指定名字时:索引名:为最左
联合索引最左原则:一定要保证联合索引最左的字段出现在查询条件里。
1、只写最左
2、组合查询
MySQL索引使用原则:
优点: 相对于传统意义上的索引,减少了磁盘的开销。
缺点:费时费磁盘空间
经常更新的表不要做索引数据量小不要建索引(浪费磁盘空间)相同值多的字段不要建立索引。
闭包
闭包的概念:
满足一下三个条件:
1、在函数嵌套的前提下
2、内部函数使用了外部函数的变量(包括参数)
3、外部函数返回了内部函数。
eg:
def func_ex():
i=5;
def func_in(i)
j=6
return = i+j # 内部函数使用了外部函数的变量
return func_in # 外部函数返回了内部函数
f = func_ex();因为func_ex()返回的结果是:func_in
即 f = func_in
所以执行闭包为:
f()
当内部函数使用完外部函数变量时,变量会销毁。(变量引用计数=0)
闭包的优缺点:
闭包保存外部函数变量,提高代码重用性。
缺点:由于外部函数变量没有及时释放,消耗内存。
闭包的使用:
def name(name):
''' 外部函数
:param name:
:return: '''
def infos(info):
''' 内部函数
:param info:
:return:
'''
print(name+":"+info)
return infos
tom = name("Tom")
tom('您好!我是Tom') # Tom:您好!我是Tom
tom("请问您是bobo吗?") # Tom:请问您是bobo吗?
print("tom",id(tom)) # tom 139761563047864 两个函数地址不一样
bobo = config_name("bobo")
bobo("你好Tom我不是bobo")
print("tom",id(bobo)) # tom 139761563048000tom("我今天要去找你!") # Tom:我今天要去找你!
bobo("不行哟,我今天没空") # bobo:不行哟,我今天没空# 闭包 可提高代码的
复用性。是很多对象实现的是同一功能。
修改闭包内使用的外部变量
nonlocal
装饰器
给已有函数添加额外功能的函数,本质上是一个闭包函数。
装饰器的功能特点:
1、不修改已有函数的源代码
2、不修改已有函数的调用方式
3、给已有函数添加额外的功能
开放、封闭的原则:
已经实现的代码不允许寻修改——增加新功能——单独开发功能,调用别人的功能。
# 定义一个装饰器
def decrator(func1):
def inner():
print("我是新增功能")
func1()
return inner
#定义一个需要被装饰的函数
def func():
for i in range(10):
print(i)
# 使用装饰器来装饰该函数
func = decrator(func)
# 执行
func()
装饰器的使用:
import time
# 定义一个装饰器
def time_coun(fn):
def inner():
begin = time.time()
fn()
end = time.time()
print("执行时间:%s" %(end-begin))
return inner
# 需要装饰的函数
@ time_coun # func = time_coun(func)
def func():
for i in range(10000):
print(i)
func()
带参数
# 整体是一个闭包含数,通过闭包函数可以得到一个闭包或者闭包实例
# 内部函数是一个闭包
# def func_out():
# a = 10
# def inner():
# pass
# return inner
def decorator(fn): # 装饰器闭包函数的参数只能有一个并且是函数类型,才能是装饰器。
def inner(num1,num2):
print("新增的功能")
fn(num1,num2) # 此处的fn 是最初带两个参数的待装饰函数
return inner
# 当下面这个这个模块“加载”完成 就立刻执行装饰器,对函数进行装饰。
@decorator # sum_num = decorstor(sum_num) 为了不改变原来的调用方式
# 需要装饰的函数
def sum_num(a,b):
print(a+b)
# 调用函数
sum_num(2,3) # 此时sum_num = inner