一条SQL语句在MySQL中如何执行的

  • MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。
  • 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。
  • SQL 等执行过程分为两类,一类对于查询等过程如下:权限校验—-》查询缓存—-》分析器—-》优化器—-》权限校验—-》执行器—-》引擎
  • 对于更新等语句执行流程如下:分析器——》权限校验——》执行器—-》引擎—-redo log prepare—-》binlog—-》redo log commit

一条SQL语句在MySQL中如何执行的

一条SQL语句执行得很慢的原因有哪些?

一个 SQL 执行的很慢,我们要分两种情况讨论:

  1. 大多数情况下很正常,偶尔很慢,则有如下原因
    1. 数据库在刷新脏页,例如 redo log 写满了需要同步到磁盘。
    2. 执行的时候,遇到锁,如表锁、行锁。
  2. 这条 SQL 语句一直执行的很慢,则有如下原因。
    1. 没有用上索引:例如该字段没有索引;由于对字段进行运算、函数操作导致无法用索引。
    2. 数据库选错了索引。

腾讯面试:一条SQL语句执行得很慢的原因有哪些?—-不看后悔系列

数据库三范式

  • 第一范式:列不可分,保证列的原子性。例如:一个列为“地址”,包括了省、市、区,那么这一列就不符合第一范式
  • 第二范式:非主键字段完全依赖于主键。第二范式是在第一范式的基础上建立起来的,它要求每行都能被唯一地区分。例如员工信息表中加上了员工编号,因为每个员工的员工编号是惟一的,因此每个员工可以被惟一区分。这个惟一属性列被称为主关键字或主键、主码。 每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。
  • 第三范式:第三范式要求必须先满足第二范式。第三范式要求数据库表中不包含已经在其它表中已经包含的信息。例如一个部门信息表,其中有部门编号、部门名称等,那么在员工信息表中列出部门编号后就不能再将部门名称。

SQL 注入

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。但凡有SQL注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成SQL语句的一部分。

场景:程序接受客户端输入的变量或者参数组成 SQL 语句的一部分,这时攻击者通过输入的参数修改原来的逻辑,比如在密码判断语句后面加上 or 1=1,实现无账号登录等。

  1. String sql = "select * from user_table where username=
  2. ' "+userName+" ' and password=' "+password+" '";
  3. --当输入了上面的用户名和密码,上面的SQL语句变成:
  4. SELECT * FROM user_table WHERE username=
  5. '’or 1 = 1 -- and password='
  6. """
  7. --分析SQL语句:
  8. --条件后面username=”or 1=1 用户名等于 ” 或1=1 那么这个条件一定会成功;
  9. --然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都--能正确执行,用户轻易骗过系统,获取合法身份。
  10. --这还是比较温柔的,如果是执行
  11. SELECT * FROM user_table WHERE
  12. username='' ;DROP DATABASE (DB Name) --' and password=''
  13. --其后果可想而知…
  14. """

如何防止 SQL 注入

  1. 检查变量数据类型和格式

只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL注入攻击。如果是接受邮箱,那就应该检查并严格确保变量一定是邮箱的格式,其他的类型比如日期、时间等也是一个道理。

  1. 过滤特殊符号

对于无法确定固定格式的变量,一定要进行特殊符号过滤或转义处理。

  1. 绑定变量,使用预编译语句

使用预编译语句可以将sql语句模板化或者说参数化,对传入的参数进行强制类型检查和安全检查,避免SQL注入的产生。
参数化能防注入的原因在于,语句是语句,参数是参数,参数的值并不是语句的一部分