数据库事务【重点】、数据库单库备份、数据库多库备份、数据库全部备份、重新导入数据库文件



day 05  数据库

    
    1.pymysql
        
        介绍:
            Python操作mysql的模块
        安装:
            pip install mysql
        
        连接:
            import pymysql
            conn = pymysql.connect(host='主机名', user='用户名', password='密码', database='数据库名',charset='utf8');
            
            cursor = conn.cursor()  ### 返回的是元祖套元祖
            cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) ### 返回的是列表套字典
        
        执行sql语句:
            cursor.execute(sql)
        
        查:
            fetchall() : 获取多个, 返回 列表套字典
            fetchone() : 获取一个, 返回 字典
            fetchmany(size) : 获取size个数据, 返回的是 列表套字典
        
        增删改:
            
            conn.commit()
            
        SQL注入:
            原因:
                太相信用户输入的数据
                
            解决的方法:
                # sql = "select * from user where name='%s' and password='%s'" % (user, pwd)
                sql = "select * from user where name=%s and password=%s"

                cursor.execute(sql, (user, pwd))
        csrf攻击
        
        
    
    2.索引
        
        a.索引的作用?
            提高查询的效率
        
        b.类比:字典中的目录
        
        c.底层采用的数据结构:(******************)
            B+树
            
        d.索引本质上就是一个特殊的文件, 只不过这个特殊的文件底层的数据结构是B+树
            
        
        e.索引的分类:
        
            - 主键索引
                
                作用: 加快查询速度 + 不能重复 + 不能为空
                
                增加:
                    
                    第一种方法:(**********************)
                        create table user (
                            id int auto_increment primary key,  ### 主键自增id
                        )
                        
                        注意:auto_increment 依赖 primary key, 而primary key 不依赖auto_increment
                    
                    第二种方法:
                        alter table user change id id int auto_increment primary key;
                删除:
                    
                    如果要删除带有 auto_increment的primary key的话, 需要提前删除auto_increment
                    alter table user change id id int  primary key;
                    
                    然后再删除
                    alter table user drop primary key;
                
                场景:
                    一般都是加在 id 这一列
                
                技术是服务于业务的
                
                    
            - 唯一索引
                作用: 加快查询速度 + 不能重复 
                
                增加: 
                    
                    第一种方法:
                        
                        create table user (
                            id int auto_increment primary key,
                            phone int not null default 0,
                            name varchar(32)
                            unique ix_phone(索引名) (phone(字段名))
                        )
                    
                    第二种方法:  
                        alter table user add unique index ix_phone (phone);
                    
                    第三种方法:
                        create unique index ix_phone on user (phone);
                
                
                删除: 
                    alter table user drop index ix_phone;
                
                
                场景: 
                    应用在唯一值得时候,根据自己的业务去定
                    脱离业务谈技术就是耍流氓
                    
                
                - 联合唯一索引
                
                    使用方法同上
                    
                    场景: 
                        根据项目或者业务方的需求,灵活的加上联合唯一索引
                        
                例子:
                    create table user (
                        id int auto_increment primary key,
                        a int not null default 0,
                        b int not null default 0,
                        unique ix_ab (a,b)
                    )charset utf8;

                    insert into user (a,b) values (1,2);
                    insert into user (a,b) values (1,3);
                    insert into user (a,b) values (3,2);
                    
                    mysql> insert into user (a,b) values (1,2);
                    ERROR 1062 (23000): Duplicate entry '1-2' for key 'ix_ab'
                    mysql>
                    mysql> insert into user (a,b) values (1,3);
                    Query OK, 1 row affected (0.05 sec)
                    
                
            - 普通索引
                
                
                作用:加速查找
                
                增加: 
                    
                    第一种方法:  
                        create table user (
                            id int auto_increment primary key,
                            name varchar(32) not null default '',
                            index ix_name (name)
                        )
                        
                    第二种方式:
                        alter table user add index ix_name (name);
                        
                    
                    第三种方法:
                        create  index ix_name on user (name);
                
                删除: 
                    alter table user drop index ix_name;
                    
                
                - 联合(组合)索引
                    index(name, age)
                    
        
        f.索引的命中:
            索引加的越多越好?
                
                不是
            
            不会命中索引的情况:
                
                a. 不能在SQl语句中,进行四则运算, 会降低SQL的查询效率
                
                b. 使用函数
                    select * from tb1 where reverse(email) = 'zekai';
                c. 类型不一致
                    如果列是字符串类型,传入条件是必须用引号引起来,不然...
                    select * from tb1 where email = 999;
                
                #排序条件为索引,则select字段必须也是索引字段,否则无法命中
                d. order by
                    select name from s1 order by email desc;
                    当根据索引排序时候,select查询的字段如果不是索引,则速度仍然很慢
                    
                    select email from s1 order by email desc;
                    特别的:如果对主键排序,则还是速度很快:
                        select * from tb1 order by nid desc;
                        
                e. count(1)或count(列)代替count(*)在mysql中没有差别了
                
                f. 组合索引最左前缀
                    
                    什么时候会创建联合索引?
                        
                        根据公司的业务场景, 在最常用的几列上添加索引
                        
                        select * from user where name='zekai' and email='[email protected]';
                        
                        如果遇到上述业务情况, 错误的做法:
                            index ix_name (name),
                            index ix_email(email)
                        
                        正确的做法:
                            index ix_name_email(name, email)
                            
                        
                    
                    如果组合索引为:ix_name_email (name,email) ************
                    
                        where name='zekai' and email='xxxx'       -- 命中索引
                    
                        where name='zekai'   -- 命中索引
                        where email='[email protected]'                -- 未命中索引
                    
                    如果组合索引为:ix_name_email_age (name, email, age):
                    
                        where name='zekai' and email='xxx' and age=12;  ---- 命中索引
                        where name='zekai' and age=12;              ---- 命中索引
                        
                        mysql> explain select * from user where name='zekai' and email='[email protected]' and age=12 \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: ref
                        possible_keys: ix_name_email_age
                                  key: ix_name_email_age
                              key_len: 218
                                  ref: const,const,const
                                 rows: 1
                             filtered: 100.00
                                Extra: Using index
                        1 row in set, 1 warning (0.00 sec)

                        mysql> explain select * from user where name='zekai'  and age=12 \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: ref
                        possible_keys: ix_name_email_age
                                  key: ix_name_email_age
                              key_len: 62
                                  ref: const
                                 rows: 1
                             filtered: 10.00
                                Extra: Using where; Using index
                        1 row in set, 1 warning (0.00 sec)

                        mysql> explain select * from user where email='[email protected]'  and age=12 \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: index
                        possible_keys: NULL
                                  key: ix_name_email_age
                              key_len: 218
                                  ref: NULL
                                 rows: 2987635
                             filtered: 1.00
                                Extra: Using where; Using index
                        1 row in set, 1 warning (0.00 sec)

                        mysql> explain select * from user where age=12 \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: index
                        possible_keys: NULL
                                  key: ix_name_email_age
                              key_len: 218
                                  ref: NULL
                                 rows: 2987635
                             filtered: 10.00
                                Extra: Using where; Using index
                        1 row in set, 1 warning (0.00 sec)

                        mysql> explain select * from user where email=12 \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: index
                        possible_keys: NULL
                                  key: ix_name_email_age
                              key_len: 218
                                  ref: NULL
                                 rows: 2987635
                             filtered: 10.00
                                Extra: Using where; Using index
                        1 row in set, 1 warning (0.00 sec)

                        mysql> explain select * from user where email='[email protected]' \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: index
                        possible_keys: NULL
                                  key: ix_name_email_age
                              key_len: 218
                                  ref: NULL
                                 rows: 2987635
                             filtered: 10.00
                                Extra: Using where; Using index
                        1 row in set, 1 warning (0.00 sec)

                        mysql> explain select * from user where name='zekai' \G
                        *************************** 1. row ***************************
                                   id: 1
                          select_type: SIMPLE
                                table: user
                           partitions: NULL
                                 type: ref
                        possible_keys: ix_name_email_age
                                  key: ix_name_email_age
                              key_len: 62
                                  ref: const
                                 rows: 1
                             filtered: 100.00
                                Extra: Using index
                        1 row in set, 1 warning (0.00 sec)
                    
                        mysql> tee D:/a.log
                        Logging to file 'D:/a.log'
                        
                    
                    
                explain  
        
                
                g.慢日志:
                    
                    查询:
                        show variables like '%slow%';
                        mysql> show variables like '%slow%'
                            -> ;
                        +---------------------------+-----------------------------------------------+
                        | Variable_name             | Value                                         |
                        +---------------------------+-----------------------------------------------+
                        | log_slow_admin_statements | OFF                                           |
                        | log_slow_slave_statements | OFF                                           |
                        | slow_launch_time          | 2                                             |
                        | slow_query_log            | OFF   ### 默认关闭慢SQl查询日志, on                                          |
                        | slow_query_log_file       | D:\mysql-5.7.28\data\DESKTOP-910UNQE-slow.log | ## 慢SQL记录的位置
                        +---------------------------+-----------------------------------------------+
                        5 rows in set, 1 warning (0.08 sec)
                        
                        mysql> show variables like '%long%';
                        +----------------------------------------------------------+-----------+
                        | Variable_name                                            | Value     |
                        +----------------------------------------------------------+-----------+
                        | long_query_time                                          | 10.000000 |
                
                
                排查慢SQL的原因:
                    
                    1. 将慢SQL记录到日志中
                    
                    2. 获取慢SQl,根据慢SQL来优化查询效率 (加索引或者修改索引)



今日内容:

    1.作业题
        
    
    2.事务
        通俗的说,事务指一组操作,要么都执行成功,要么都执行失败

        思考:
            我去银行给朋友汇款,
            我卡上有1000元,
            朋友卡上1000元,
            我给朋友转账100元(无手续费),
            如果,我的钱刚扣,而朋友的钱又没加时,
            网线断了,怎么办?
        
        演示:
            create table user (
                id int auto_increment primary key,
                name varchar(32) not null default '',
                salary int not null default 0
            )charset utf8;
            
            insert into user (name, salary) values ('zekai', 1000);
            insert into user (name, salary) values ('min', 1000);
            
        解决的方法:
            使用事务:
                start transaction;
                    sql语句
                commit/rollback;
            
            例子: 
                commit成功:
                mysql> start transaction;
                Query OK, 0 rows affected (0.00 sec)

                mysql> update user set salary=900 where name='zekai';
                Query OK, 1 row affected (0.01 sec)
                Rows matched: 1  Changed: 1  Warnings: 0

                mysql> select * from user;
                +----+-------+--------+
                | id | name  | salary |
                +----+-------+--------+
                |  1 | zekai |    900 |
                |  2 | min   |   1000 |
                +----+-------+--------+
                2 rows in set (0.00 sec)

                mysql> update user set salary=1100 where name='min';
                Query OK, 1 row affected (0.00 sec)
                Rows matched: 1  Changed: 1  Warnings: 0

                mysql> select * from user;
                +----+-------+--------+
                | id | name  | salary |
                +----+-------+--------+
                |  1 | zekai |    900 |
                |  2 | min   |   1100 |
                +----+-------+--------+
                2 rows in set (0.00 sec)

                mysql> #2.提交
                mysql> commit;
                Query OK, 0 rows affected (0.06 sec)
                
                rollback回滚:
                    mysql> start transaction;
                    Query OK, 0 rows affected (0.00 sec)

                    mysql>
                    mysql>
                    mysql> update user set salary=800 where name='zekai';
                    Query OK, 1 row affected (0.01 sec)
                    Rows matched: 1  Changed: 1  Warnings: 0

                    mysql> select * from user;
                    +----+-------+--------+
                    | id | name  | salary |
                    +----+-------+--------+
                    |  1 | zekai |    800 |
                    |  2 | min   |   1100 |
                    +----+-------+--------+
                    2 rows in set (0.00 sec)

                    mysql> rollback;
                    Query OK, 0 rows affected (0.11 sec)

                    mysql> select * from user;
                    +----+-------+--------+
                    | id | name  | salary |
                    +----+-------+--------+
                    |  1 | zekai |    900 |
                    |  2 | min   |   1100 |
                    +----+-------+--------+
                    2 rows in set (0.00 sec)
                
                rollback回滚,影响所有:
                    
                    mysql> start transaction;
                    Query OK, 0 rows affected (0.00 sec)
                    
                    mysql> update user set salary=800 where name='zekai';
                    Query OK, 1 row affected (0.00 sec)
                    Rows matched: 1  Changed: 1  Warnings: 0

                    mysql> update user set salary=700 where name='zekai';
                    Query OK, 1 row affected (0.00 sec)
                    Rows matched: 1  Changed: 1  Warnings: 0

                    mysql> select * from user;
                    +----+-------+--------+
                    | id | name  | salary |
                    +----+-------+--------+
                    |  1 | zekai |    700 |
                    |  2 | min   |   1100 |
                    +----+-------+--------+
                    2 rows in set (0.00 sec)

                    mysql> rollback;
                    Query OK, 0 rows affected (0.05 sec)

                    mysql> select * from user;
                    +----+-------+--------+
                    | id | name  | salary |
                    +----+-------+--------+
                    |  1 | zekai |    900 |
                    |  2 | min   |   1100 |
                    +----+-------+--------+
                    2 rows in set (0.00 sec)
                    
            特性:(****************)
                原子性(Atomicity),原子意为最小的粒子,即不能再分的事务,要么全部执行,要么全部取消(就像上面的银行例子)
                一致性(Consistency):指事务发生前和发生后,数据的总额依然匹配
                隔离性(Isolation):简单点说,某个事务的操作对其他事务不可见的
                持久性(Durability):当事务完成后,其影响应该保留下来,不能撤消,只能通过“补偿性事务”来抵消之前的错误
                
            存储引擎:(**************)
                
                InnoDB  : 保时捷引擎
                
                MyIsam  : 奔奔引擎
                
                建表的时候,
                    create table user (
                        id int auto_increment primary key,
                        name varchar(32) not null default '',
                        salary int not null default 0
                    )engine=Innodb charset utf8;
                
                mysql5.5以上, 默认用到就是InnoDB
                
                两个引擎的区别:(**************)
                    1. Innodb支持事务,MyISAM不支持
                    2. InnoDB支持行锁,MyISAM支持的表锁
                    
                

        
    3.视图
        
        项目, 有100个SQl, 其中80个SQL都是:select * from user where name='xxx';
        
        
        增加视图:
            create view 视图名 as SQL语句;
        
        删除: 
            drop view v1;
        
        例子:
            mysql> select * from user where name='zekai';
            +----+-------+--------+
            | id | name  | salary |
            +----+-------+--------+
            |  1 | zekai |    900 |
            +----+-------+--------+
            1 row in set (0.00 sec)


            mysql> create view v1 as select * from user where name='zekai';
            Query OK, 0 rows affected (0.07 sec)

            mysql>
            mysql> show tables;
            +-----------------+
            | Tables_in_test3 |
            +-----------------+
            | user            |
            | v1              |
            +-----------------+
            2 rows in set (0.00 sec)

            mysql> select * from v1;
            +----+-------+--------+
            | id | name  | salary |
            +----+-------+--------+
            |  1 | zekai |    900 |
            +----+-------+--------+
            1 row in set (0.00 sec)
        
        
    
    4.触发器
        
        两张表:
            订单表     库存表
            
        场景:
            当我下一个订单的时候, 订单表中需要增加一个记录, 同时库存表中需要减1
            这两个操作是同时发生的,  并且前一个操作出发后一个操作
        
        使用方法:
            
            增加:
                delimiter //
                
                CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON t2 FOR EACH ROW
                BEGIN
                    INSERT INTO t3 (NAME) VALUES ('aa');
                END //
                
                delimiter ;
            
            ### 当向tb1表中添加一条数据的同时, 向tb2表添加一条数据
            
            查看:
             show triggers\G
                *************************** 1. row ***************************
                             Trigger: tri_before_insert_tb1
                               Event: INSERT
                               Table: t2
                           Statement: BEGIN
                INSERT INTO t3 (NAME) VALUES ('aa');
                END
                              Timing: BEFORE
                             Created: 2019-11-01 11:47:20.65
                            sql_mode: ONLY_FULL_GROUP_BY
                             Definer: root@localhost
                character_set_client: gbk
                collation_connection: gbk_chinese_ci
                  Database Collation: latin1_swedish_ci
            
            删除:drop trigger 触发器名;
            
            例子:
                mysql> select * from t2;
                Empty set (0.00 sec)

                mysql> select * from t3;
                Empty set (0.00 sec)
                mysql> insert into t2 (name) values ('zekai');
                Query OK, 1 row affected (0.06 sec)

                mysql> select * from t2;
                +----+-------+
                | id | name  |
                +----+-------+
                |  1 | zekai |
                +----+-------+
                1 row in set (0.00 sec)

                mysql> select * from t3;
                +----+------+
                | id | name |
                +----+------+
                |  1 | aa   |
                +----+------+
                1 row in set (0.00 sec)
            
            
    5.存储过程
        
        像  一个 SQL函数
        
        创建:
            
            delimiter //
        
            create procedure p1()
            BEGIN
                select * from user where id=2;
            END //
            
            delimiter ;
        
        例子:
            
            mysql> delimiter //

            mysql> create procedure p1()
                -> BEGIN
                -> select * from user where id=2;
                -> END //
            Query OK, 0 rows affected (0.10 sec)

            mysql> delimiter ;

            mysql> call p1();
            +----+------+--------+
            | id | name | salary |
            +----+------+--------+
            |  2 | min  |   1100 |
            +----+------+--------+
            1 row in set (0.00 sec)

            Query OK, 0 rows affected (0.01 sec)
            
        删除:
            drop procedure p1;
        
        
    
    6.函数
        CHAR_LENGTH(str)
            返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。
            对于一个包含五个二字节字符集, LENGTH()返回值为 10, 而CHAR_LENGTH()的返回值为5。
        
        CONCAT(str1,str2,...)
            字符串拼接
            如有任何一个参数为NULL ,则返回值为 NULL。
        FORMAT(X,D)
            将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。
            例如:
                SELECT FORMAT(12332.1,4); 结果为: '12,332.1000'
        INSTR(str,substr)
            返回字符串 str 中子字符串的第一个出现位置。
        LEFT(str,len)
            返回字符串str 从开始的len位置的子序列字符。
        LOWER(str)
            变小写
        UPPER(str)
            变大写
        LTRIM(str)
            返回字符串 str ,其引导空格字符被删除。
        RTRIM(str)
            返回字符串 str ,结尾空格字符被删去。
        SUBSTRING(str,pos,len)
            获取字符串子序列
        LOCATE(substr,str,pos)
            获取子序列索引位置
        REPEAT(str,count)
            返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count 。
            若 count <= 0,则返回一个空字符串。
            若str 或 count 为 NULL,则返回 NULL 。
        REPLACE(str,from_str,to_str)
            返回字符串str 以及所有被字符串to_str替代的字符串from_str 。
        REVERSE(str)
            返回字符串 str ,顺序和字符顺序相反。
        RIGHT(str,len)
            从字符串str 开始,返回从后边开始len个字符组成的子序列
        
        
        http://doc.mysql.cn/mysql5/refman-5.1-zh.html-chapter/functions.html#encryption-functions
        
        
        
        
    7.运维方向:
        数据库的备份
        
            为啥要备份?
                将重要的数据保存下来
            
            用法:
                #语法:
                # mysqldump -h 服务器 -u用户名 -p密码 数据库名 表名,  表名,.... > aaa.sql

                #示例:
                #单库备份
                mysqldump -uroot -p123 db1 > db1.sql
                mysqldump -uroot -p123 db1 table1 table2 > db1-table1-table2.sql

                #多库备份
                mysqldump -uroot -p123 --databases db1 db2 mysql db3 > db1_db2_mysql_db3.sql

                #备份所有库
                mysqldump -uroot -p123 --all-databases > all.sql
        
            重新导入:
                mysql> source D:/test3.sql;









猜你喜欢

转载自www.cnblogs.com/ludundun/p/11778326.html