MySQL的触发器、存储过程与读写分离

来源:互联网 发布:js鼠标滚动条事件 编辑:程序博客网 时间:2024/05/21 06:57
1、解发器 trigger
     触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力。应用在表中某些数据的改变需要引起其他相关数据的改变的需求,它不仅可以简化程序,而且还可以增加程序的灵活性。目前在公司中还没有遇到过使用触发器的,不过我们可以把他用到数据同步上,比如两个结构不一样库的的同步上。
     触发器是一类特殊的事件,可以监听某种数据操作(insert、update、delete)并触发相关操作(insert、update、delete)。
     需求一:有一个商品表goods,订单表ord,当下一个订单时商品数量减少
     设置定界符:默认是;号,delimiter $
          create trigger t1
          after
          insert
          on ord
          for each row
          begin
          update goods set num=num-new.much where id=new.goods;
          end$
     
     查看已有触发器:show triggers
     删除触发器:drop trigger triggerName
     在新增时的变量用new.字段名,删除时为old.字段,修改时为:改之前为old.字段,改之后用new.字段


     需求二:如果在购买时,much>库存量则最大只允许他买库存数量,此时要用到before
          create trigger t2
          after
          insert
          on ord
          for each row
          
          declare
          rnum int;


          begin


          select num into rnum from goods where id=new.goods;
          if new.much>rnum
               set new.much = rnum;
          end if     
          update goods set num=num-new.much where id=new.goods;


          end$
     
     before和after的区别:即将操作之前和操作之后。
     触发器都有一个for each row,它表示行级触发器,每受影响一行就行执行一次,比如update时,更改了100条数据,则监听update的行级触发器就会执行100次,遗憾的是MySQL暂时不支持语句级触发器,Oracle是可以的。


2、存储过程
     触发器也是一种存储过程,存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。你会觉得很像函数。
     优点:
①重复使用。存储过程可以重复使用,从而可以减少数据库开发人员的工作量。
②提高性能。存储过程在创建的时候在进行了编译,将来使用的时候不再重新翻译。一般的SQL语句每执行一次就需要编译一次,所以使用存储过程提高了效率。
③减少网络流量。存储过程位于服务器上,调用的时候只需要传递存储过程的名称以及参数就可以了,因此降低了网络传输的数据量。
④安全性。参数化的存储过程可以防止SQL注入式攻击,而且可以将Grant、Deny以及Revoke权限应用于存储过程。
      语法:
        创建:
          create procedure procedureName()
          begin
                --SQL语句
          end
查看存储过程:
      show procedure status
  调用存储过程:
      call procedureName();
      使用结构语句编程:
          使用declare声明变量:
                declare 变量名 变量类型 [default 默认值]
          变量的赋值:
                set 变量名 := 变量值;
          if/else选择结构:
                if age>=18 then  
                    --
                else
                    --
                end;
        给存储过程传参数:
               定义形参:create procedure procedureName(width int,height int)
                               这里注意in和out型的参数,in传入,out传出,in out既是传入又是传出型。在调用时要传入变量
               调用传参:procedureName(12,20);
                              
          while循环:
                declare num int default 0;
                while num<100 do
                    set num := num+1;
                end while;
          case 结构
                case num
                    when 1 then ....;
                    when 2 then ...;
                    else ...
                end case
3、游标:
          游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果。每个游标区都有一个名字。用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。
          1、游标允许应用程序对查询语句select 返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作;
          2、它还提供对基于游标位置而对表中数据进行删除或更新的能力;
          3、游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。 
          然尔游标也有缺点——复杂和低效,是游标的最大缺点,也是致使很多时候在使用存储过程中没有想到游标的主要原因。
          
          注意游标越界,可以利用标识来结束

4、用户权限
     1、你有没有权限连接,存储在mysql.users中
        你是谁? username
          你从哪儿来? host
          你的帐号密码多少? password
     2、你有没有权执行此操作
               授权一个用户:
                grant [权限1,权限2,权限3...] on *.* to user@"host" identified by 'password'
                常见的权限有:all、create、drop、insert、delete、update、select
               针对某库做授权
                    grant all on ecshop.*  to username@'192.168.1.%'
               针对某表做授权
                    grant create,drop,insert,update,select on ecshop.ecs_order to userName@'192.158.0.%'
               回收权限,将上面的grant改为revoke
               应用:在程序中有些表上数据是原始数据,不能被删除,除了在PHP业务逻辑中控制,更可靠的是禁用掉对某表的操作
               给可以针对某列做授权

5、主从复制(读写分离)
      主:master
      从:slave
      希望主服务器数据有任何改变,从服务器跟着同步过去
      1、采用这种架构可以提高稳定性,如果某一台务器发生故障,我们可以使用其他从服务器提供服务。
      2、数据更不易丢失。
      3、减少数据库压力,提升数据处理效率。

读的效率提高了,如果提高写呢?这是个问题,从硬件入手:使用SSD硬盘。得好好想下当“写”服务撑不住的时候,怎么办。
在linux下的配置:
       
  准备:两台MySQL的服务器版本最好一致。两边的数据库、表、值等等保持一致。如果不一致先备份成一致。
          1、配置主服务器master
               vi /etc/my.cnf
                    [mysqld]
                           log-bin=mysql-bin   //[必须]启用二进制日志
                           server-id=129         //[必须]服务器唯一ID,默认是1,一般取IP最后一段     
          2、配置从服务器Slave
                vi /etc/my.cnf
                    [mysqld]
                           log-bin=mysql-bin   //[必须]启用二进制日志
                           server-id=130         //[必须]服务器唯一ID,默认是1,一般取IP最后一段
           3、启动两台MySQL服务器
                /usr/local/mysql/bin/mysqld_safe &
           4、在主服务器上建立帐户并授权Slave
                /usr/local/mysql/bin/mysql -uroot -p 
                GRANT REPLICATION SLAVE ON *.* TO 'sync'@'%' identified by '123456'
                一般不用root帐号,%表示客户端都可以连接,不区分来至哪些IP,你也可以填写某IP增强安全。sync是创建的帐号,123456是帐号密码
          5、查看主服务器的master状态
               
show master status;
               记录下主服务器状态Position的值,后面配置从服务器要用到(注意不要再操作主服务器了,以免服务器状态值发生变化了)
           6、配置从服务器Slave
                    change master to master_host='192.168.135.129',master_user='sync',master_password='123456',master_log_file='mysql-bin.000006',master_log_pos=249;  
                     解释:
                         master_host是主服务器的ip
                         master_user是主服务器的创建的slave帐号
                         master_password 与帐号对应的密码
                         249是主服务器状态值
                         master_log_file是同步日志文件名,由上一步得到的服务器状态值。
          7、启动从服务器Slave的复制功能
                   mysql>  start slave;
          8、检查从服务器复制功能状态:
                   mysql> show slave status\G;
 

如上我们看到了Slave_IO_Running:connecting表示不对的,一般会有三个原因导致该问题:
           
a、网络不通(检查防火墙)
           
b、密码错误
           
c、从库配置的主库状态信息不对
            检查后发现我配置从库时的File点号前手抖多了一个逗号,检查日志查看错误是最有效的。
               于是先停掉从库slave:slave stop
               再重新查看服务器状态值重新配置Slave并重新启动slave
          9、测试主从同步
              在master服务器创建一个数据库,创建一张表并写入数据后发现slav服务器已经同步过来了。
              在mysql下次重启时不需要重新配置,配置好后slave会跟随启动



0 0
原创粉丝点击