2018年度知识总结

一、php部分

1、php内置函数使用

1、trim($string ,$need) 移除字符串两侧的空白字符或其他预定义字符。
接收input流时使用,当$need 省略时,如果被省略,则移除以下所有字符
“\0” - NULL
“\t” - 制表符
“\n” - 换行
“\x0B” - 垂直制表符
“\r” - 回车
" " - 空格

2、strlen($str) mb_strlen($str,charset) 统计字符串长度

3、substr($str,$start,$length) mb_substr($str,$start,$length,charset) 截取字符串

4、explode($char,$string,$limit) c h a r 为 标 准 将 char 为标准 将 charstring 分割成数组 $limit 为可选个数

5、implode($char,$arr) a r r 已 arr 已 arrchar 组合成字符串 $char 默认是’’

6、in_array($need,$arr) 判断 a r r 的 v a l u e 中 是 否 存 在 arr的value中是否存在 arrvalueneed
array_key_exists($need,$arr) 判断 a r r 的 k e y 中 是 否 存 在 arr的key中是否存在 arrkeyneed

7、array_unique($arr) 去除$arr 中的重复数据

8、array_search($val,$arr,$strict) 查找数组中指定 v a l 的 val 的 valkey ,$strict默认false,true 时 $val 的数据类型一致

9、str_replace($find,$replace,$string,$count) t r i n g 中 查 找 tring中查找 tringfind, r e p l a c e 代 替 replace 代替 replacefind ,$count可选 替换数量

10、header(string,replace,http_response_code)
string 必需。规定要发送的报头字符串。
replace 可选。指示该报头是否替换之前的报头,或添加第二个报头。
默认是 true(替换)。false(允许相同类型的多个报头)。
http_response_code 可选。把 HTTP 响应代码强制为指定的值。(PHP 4 以及更高版本可用)
解决跨域问题 header('Access-Control-Allow-Origin: *');

11、array_merge($arr,$arr2...)将多个数组合并成一个数组

12、array_push($arr,$val) v a l 添 加 到 val 添加到 valarr中 ,$val 可是多个,可是是数组

13、array_diff($a1,$a2) 返回 a 1 与 a1与 a1a2 数组的差集

14、array_intersect($a1,$a2) 返回 a 1 与 a1与 a1a2 数组的交集

15、compact($a,$a2) 创建包含变量名和它们的值的数组。$a = 124 >>> [‘a’=>124]

16、array_column($arr,$column_key,$index_key) 回输入数组中某个单一列的值。 拼接数据常用
$arr 规定要使用的多维数组(记录集)。
column_key 需要返回值的列。可以是索引数组的列的整数索引,或者是关联数组的列的字符串键值。该参数也可以是 NULL,此时将返回整个数组(配合 index_key 参数来重置数组键的时候,非常有用)。
index_key 可选。用作返回数组的索引/键的列。

17、浏览器跑报表在头部设置
ini_set(‘memory_limit’, ‘3072M’); // 临时设置最大内存占用为3G ini_set
set_time_limit(0); // 设置脚本最大执行时间 为0 永不过期
ini_set(‘max_execution_time’, 0);

2、常用自定义方法

1、姓名隐藏 张三> 张*
 function name_hidden($user_name)
    {
        $strlen = mb_strlen($user_name, 'utf-8');
        $firstStr = mb_substr($user_name, 0, 1, 'utf-8');
        $lastStr = mb_substr($user_name, -1, 1, 'utf-8');
        return $strlen == 2 ? 
        $firstStr . str_repeat('*', mb_strlen($user_name, 'utf-8') - 1) :
        $firstStr . str_repeat("*", $strlen - 2) . $lastStr;
    }
2、无限级分类 ,$list 为一个二维数组,含有指定的键 ,pid 为父节点,list为子节点下的数组
	 function genTree($list, $pk = 'id', $pid = 'pid', $child = 'list', $root = 0)
    {
        //创建Tree
        $tree = array();

        if (is_array($list)) {
            //创建基于主键的数组引用
            $refer = array();

            foreach ($list as $key => $data) {
                $refer[$data[$pk]] = &$list[$key];
            }

            foreach ($list as $key => $data) {
                //判断是否存在parent
                $parantId = $data[$pid];

                if ($root == $parantId) {
                    $tree[] = &$list[$key];
                } else {
                    if (isset($refer[$parantId])) {
                        $parent = &$refer[$parantId];
                        $parent[$child][] = &$list[$key];
                    }
                }
            }
        }

        return $tree;
    }
3、 根据唯一字段对两个二维数组取差集
function getDiffArrayByPk($arr1, $arr2, $pk = 'id')
{
	    try {
	        $res = [];
	        foreach ($arr2 as $item) $tmpArr[$item[$pk]] = $item;
	        foreach ($arr1 as $v) if (!isset($tmpArr[$v[$pk]])) $res[] = $v;
	        return $res;
	    } catch (\Exception $exception) {
	        return $arr1;
	    }
}
4、 二维数组去重 通过数组中的指定键名
private function assoc_unique($arr, $key)
    {
        $tmp_arr = array();
        foreach ($arr as $k => $v) {
            if (in_array($v[$key], $tmp_arr))//搜索$v[$key]是否在$tmp_arr数组中存在,若存在返回true
            {
                unset($arr[$k]);
            } else {
                $tmp_arr[] = $v[$key];
            }
        }
        sort($arr); //sort函数对数组进行排序
        return $arr;
    }
5、二维数组交集
function getUnionArray($res_repeat, $mac_array)
{
    $out_arr = array(); //交集或者是不重复的数组
    if (!empty($res_repeat)) {
        foreach ($mac_array as $key => $item) {
            if (!in_array(array("mac_addr" => $item), $res_repeat)) {
                $out_arr[] = $item;
            }
        }
    } else {
        $out_arr = $mac_array;
    }

    return $out_arr;
}
6、数组转换为xml
 public function arrayToXml($array=array()) {
        if(empty($array)) return '';
        if(is_object($array)){
            $array = get_object_vars($array);
        }
        $xml = '<xml>';
        foreach($array as $key => $value){
            $_tag = $key;
            $_id = null;
            if(is_numeric($key)){
                $_tag = 'item';
                $_id = ' id="' . $key . '"';
            }
            $xml .= "<{$_tag}{$_id}>";
            $xml .= (is_array($value) || is_object($value)) ? $this->arrayToXml($value) : htmlentities($value);
            $xml .= "</{$_tag}>";
        }
        $xml.="</xml>";
        return $xml;
    } ```
##### 7、 xml转数组
```php
function xmlToArray($xml='') {
  $array_data = json_decode(
   json_encode(
    simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)
        	), true);
        return $array_data;
    }
8、字符串截取,支持中文和其他编码

@param string $str 需要转换的字符串
@param string $start 开始位置
@param string $length 截取长度
@param string $charset 编码格式
@param string $suffix 截断显示字符
@return string

function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
    if(function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif(function_exists('iconv_substr')) {
        $slice = iconv_substr($str,$start,$length,$charset);
    }else{
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("",array_slice($match[0], $start, $length));
    }

    return ($suffix && (mb_strlen($str,$charset) > $length)) ? $slice.'...' : $slice;
}
9、获取远程图片

@param $url 图片路径
@param string $save_dir 保存目录
@param string $filename 文件名
@param int $type
return array

     function getImage($url,$save_dir='',$filename='',$type=0){
        if(trim($url)==''){
            return array('file_name'=>'','save_path'=>'','error'=>1);
        }
        if(trim($save_dir)==''){
            $save_dir='./';
        }
        if(trim($filename)==''){//保存文件名
            $ext=strrchr($url,'.');
            if($ext!='.gif'&&$ext!='.jpg'){
                return array('file_name'=>'','save_path'=>'','error'=>3);
            }
            $filename=time().$ext;
        }
        if(0!==strrpos($save_dir,'/')){
            $save_dir.='/';
        }
        //创建保存目录
        if(!file_exists($save_dir)&&!mkdir($save_dir,0777,true)){
            return array('file_name'=>'','save_path'=>'','error'=>5);
        }
        //获取远程文件所采用的方法
        if($type){
            $ch=curl_init();
            $timeout=5;
            curl_setopt($ch,CURLOPT_URL,$url);
            curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
            curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
            $img=curl_exec($ch);
            curl_close($ch);
        }else{
            ob_start();
            readfile($url);
            $img=ob_get_contents();
            ob_end_clean();
        }
        //$size=strlen($img);
        //文件大小phf
        $fp2=@fopen($save_dir.$filename,'a');
        fwrite($fp2,$img);
        fclose($fp2);
        unset($img,$url);
        return array('file_name'=>$filename,'save_path'=>$save_dir.$filename,'error'=>0);
    }
10、保存base_64图片到本地
  • @param string $base64_image_content
    * @param $path 路径
    * return bool|string
 function base64_image_content($base64_image_content,$path)
    {
        //匹配出图片的格式
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
            $type = $result[2];
            $new_file = $path . "/" . date('Ymd', time()) . "/";
            if (!file_exists($new_file)) {
                //检查是否有该文件夹,如果没有就创建,并给予最高权限
                mkdir($new_file, 0777,true);
            }
            $new_file = $new_file . time() . ".{$type}";
            if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))) {
                return  $new_file;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
11 、获取访问IP
function get_client_ip($type = 0) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if($_SERVER['HTTP_X_REAL_IP']){//nginx 代理模式下,获取客户端真实IP
            $ip = $_SERVER['HTTP_X_REAL_IP'];
        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的ip
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown',$arr);
            if(false !== $pos) unset($arr[$pos]);
            $ip = trim($arr[0]);
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的ip地址
        }else{
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u",ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }
12、php 异步请求
function sock_json($url='',$json=''){
        //解析URL
        $scheme = parse_url($url,PHP_URL_SCHEME);
        $host = parse_url($url,PHP_URL_HOST);
        $path = parse_url($url,PHP_URL_PATH);
        if($scheme == 'https') {
            $host = 'ssl://'.$host;
            $port = 443;
        }else{
            $port = 80;
        }

        $fp = fsockopen($host, $port, $error_code, $error_msg, 1);
        if (!$fp) {
            return json_encode(array('error_code' => $error_code,'error_msg' => $error_msg));
        } else {
            $out  = "POST $path HTTP/1.1\r\n";
            $out .= "Host: $host\r\n";
            $out .= "Content-Type:application/json\r\n";
            $out .= "Content-length: ".strlen($json)."\r\n";
            $out .= "Connection: Close\r\n\r\n";
            $out .= $json."\r\n\r\n";
            fputs($fp, $out);
            usleep(1000);
            fclose($fp);
            return 'ok';
        }
    } 
13 、数组导出csv

*@数据量较大时会无法导出
$file_name 导出路径,含文件名
* $header 头部
* $data 内容
* $type 1导出到服务器 2输出到浏览器

function makeCsv($file_name,$header=array(),$data=array(),$type=1){

        // 处理头部标题
        $header = implode(',', $header) . PHP_EOL;
        // 处理内容
        $content = '';
        foreach ($data as $k => $v) {
            $content .= implode(',', $v) . PHP_EOL;
        }
        // 拼接
        $csv = $header.$content;
        $csv_data = mb_convert_encoding($csv, "cp936", "UTF-8");

        if($type == 1){//保存到服务器
            // 打开文件资源,不存在则创建
            $fp = fopen($file_name,'w');
            // 写入并关闭资源
            fwrite($fp, $csv_data);
            fclose($fp);
        }else{//输出到浏览器

            $file_name = empty($file_name) ? date('Y-m-d-H-i-s', time()) : $file_name;
            if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE")) { // 解决IE浏览器输出中文名乱码的bug
                $file_name = urlencode($file_name);
                $file_name = str_replace('+', '%20', $file_name);
            }
            ob_start();
            header("Content-type:text/csv;");
            header("Content-Disposition:attachment;filename=" . $file_name);
            header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
            header('Expires:0');
            header('Pragma:public');
            echo $csv_data;
            ob_end_flush();
        }

    }
14 、大数据导出csv

$data 数组
* $filename 文件名
* $column_name 头部信息
* $k 处理的键

	    protected function exportVipOrder($data ,$filename,$column_name,$k)
    {
        set_time_limit(0);

        header ( "Content-type:application/vnd.ms-excel" );
        header ( "Content-Disposition:filename=" . iconv ( "UTF-8", "GB18030", $filename ) . ".csv" );//导出文件名

        // 打开PHP文件句柄,php://output 表示直接输出到浏览器
        $fp = fopen('php://output', 'a');

        // 将中文标题转换编码,否则乱码
        foreach ($column_name as $i => $v) {
            $column_name[$i] = iconv('utf-8', 'GB18030', $v);
        }
        // 将标题名称通过fputcsv写到文件句柄
        fputcsv($fp, $column_name);

        $total_export_count = count($data);
        $pre_count = 1000;
        $j=0;
        for ($i=0;$i<intval($total_export_count/$pre_count)+1;$i++){
            //切割每份数据

            $export_data =  array_slice($data,$i*$pre_count,$pre_count);
            //整理数据
            foreach ( $export_data as &$val ) {

                $tmpRow = [];
                $tmpRow[] =$val[$k];
             	// 数据处理

                $rows = array();
                foreach ( $tmpRow as $export_obj){
                    $rows[] = iconv('utf-8', 'GB18030', $export_obj);
                }
                fputcsv($fp, $rows);
            }

            // 将已经写到csv中的数据存储变量销毁,释放内存占用
            unset($export_data);
            ob_flush();
            flush();
        }
        exit ();

    }
15、概率算法函数
    /**
     * $proArr =array('a'=>20,'b'=>30,'c'=>50);
     */
    private function get_rand($proArr) {

        //概率数组的总概率精度
        $proSum = array_sum($proArr);
        //概率数组循环
        foreach ($proArr as $key => $proCur) {
            $randNum = mt_rand(1, $proSum);             //抽取随机数
            if ($randNum <= $proCur) {
                $result = $key;                         //得出结果
                break;
            } else {
                $proSum -= $proCur;
            }
        }
        unset ($proArr);
        return $result;
    }

3、简单的业务场景

1、限制登录次数

思路 :
1、建立一张用户登录表 ,uid(用户标识).ip, ,login_time(登录时间),status(ok/fail)
2、每次登陆时,都先从用户登录表表查询指定时间内有没有相关密码错误的记录,然后
统计一下记录总条数是否达到设定的错误次数。
3、达到次数,用户表指定用户禁用
4、如果在相同IP下,同一个用户,在指定时间内密码错误次数达到设定的错误次数,就不让用户登录了。
5、限制期过后、重新登录、若ok 修改用户表的状态

2、发放第三方券

思路
1、处理领券条件
2、查询本地是否存在用户券的信息。
3、通过指定标识查询第三方是否存在指定的券 ,有拿到券的信息
4、没有 ,通过标识创建第三方券。无论第三方券是否创建成功,都要保存数据。以便下次创建数据一致。
5、第三方核销券。返回到一个中控,
6、中控通过券的标识,分发到不同的处理url;数据库配置

3、接口安全设计

思路
接口的安全性主要围绕Token、Timestamp和Sign三个机制展开设计,保证接口的数据不会被篡改和重复调用,
1、Token授权机制:用户通过登录 服务器返回一个token 标识 通常是UUID ,并将token=>userId 通过键值对的方式缓存服务器中。服务端接收到请求后进行Token验证,如果Token不存在,说明请求无效。
2、时间戳超时机制:用户请求每次都需要带上时间戳,通过对比差值,判断请求是否有效
3、签名机制:将 Token 和 时间戳 加上其他请求参数再用指定算法(可根据情况加点盐)加密,加密后的数据就是本次请求的签名sign,服务端接收到请求后以同样的算法得到签名,并跟当前的签名进行比对,如果不一样,请求无效

4、Oauth2.0


详细解释
OAuth2 RFC6749中文翻译

5、接口防止重复提交

1、前端:JS 控制提交按钮,不能解决根本问题
2、后端:
2.1、验证码机制 :不够人性化,用户操作时间长
2.2、数据库层面加唯一索引,但是程序上要做下try catch 避免重复提交时报错
2.3 限制ip 客户端请求的时候 , 把ip记录下来,每次访问这个ip访问次数+1,如果查过制定次数,把这个ip拉黑
2.4 使用redis计数器防止并发请求
我们在接到发送请求后,使用Redis的incr设置一个递增KEY(KEY由token标识),并判断该KEY的数值,如果等于1,说明是第一个请求,我们将该KEY值有效期设置为固定时间;如果该KEY的数值大于1,说明是指定时间内的多次请求,这时我们直接返回对应的操作频繁 简单粗暴,会把确实是操作比较频繁的真实用户拦截
2.5 使用redis 缓存 。。对上次数据缓存,然后校验是否是重复提交的。

二、MySQL部分

1、函数的使用

1、 count()

通常用来统计数量
select count(0) from member;

2、Max() / Min()

获取最大值/最小值 可变形
例如获取某人最近的观看记录,去除重复的记录

SELECT
 course_id,
 Max( create_time ) AS time 
FROM
 class_member_foot_log 
WHERE
member_id = 1 
GROUP BY
course_id
ORDER BY time desc 

在这里插入图片描述

3、sum() /avg()

对数据表的某列进行求和/求平均值操作
select count(score) ,avg(score) from member_score;

4、concat() / group_concat()

将多个字符串连接成一个字符串 / 分组。
例如 统计所有文章被哪些人浏览过
这里需要结合concat() 函数 取出唯一值\

SELECT
	course_id,
	GROUP_CONCAT(DISTINCT(member_id)) 
FROM
	class_member_foot_log 
GROUP BY
	course_id

在这里插入图片描述

5 、 distinct ()

指定字段去重
例如 获取用户看过的课程数

SELECT
	count( DISTINCT ( course_id ) ) AS num,
	member_id 
FROM
	class_member_foot_log 
GROUP BY
	 member_id
6、date_format()

格式化时间 Date 函数
统计每一天看过的课程人数

SELECT
	count( DISTINCT ( member_id ) ) AS num,
	DATE_FORMAT(create_time,"%Y-%m-%d")  as time 
FROM
	class_member_foot_log 
GROUP BY
	time

在这里插入图片描述

2、控制流程函数的使用

1、if

在mysql中if()函数的用法类似于三目表达式,具体语法如下:
IF(expr1,expr2,expr3),如果expr1的值为true,则返回expr2的值,如果expr1的值为false,
判断查询出来的值
例如 查询课程是否有时间限制

SELECT
	id,
	NAME,
IF
	( is_valid_time = 0, '否', '是' )  as status
FROM
	class_course

在这里插入图片描述判断的关联条件中
例如获取当前有效的课程

SELECT
id,
NAME,
is_valid_time,
valid_start_time,
valid_end_time 
FROM
	`class_course` 
WHERE
IF
	( is_valid_time = 0, 1 = 1, NOW( ) BETWEEN valid_start_time AND valid_end_time )

在这里插入图片描述

2、case

作为条件判断

SELECT
CASE
WHEN
	is_valid_time = 0 THEN
	'否' 
WHEN is_valid_time = 1 THEN
'是' ELSE '' 
END AS status
FROM
class_course

在这里插入图片描述

3、常用查询

1、拼接用户的填写的信息地址

省市表数据结构
省市表结构图
用户填些地址数据结构
在这里插入图片描述
SQL语句

SELECT
	CONCAT(p2.name,p3.name,p4.name,p1.address) as address
FROM
	`mz_miaosha_log` AS p1
LEFT JOIN mz_area_china as p2  on  p1.province = p2.id
LEFT JOIN mz_area_china as p3  on  p1.city = p3.id 
LEFT JOIN mz_area_china as p4  on  p1.area = p4.id

在这里插入图片描述

2、多表join 查询

在这里插入图片描述

查询table_1 与 table_2 共同部分

// 方法1
SELECT
	p1.KEY,
	p2.key
FROM
	`table_1` AS p1
	left JOIN table_2 AS P2 ON P1.`key` = P2.KEY 
	where p2.key is not null 
	
// 方法2 
SELECT
	p1.KEY,
	p2.key
FROM
	`table_1` AS p1
	(inner) JOIN table_2 AS P2 ON P1.`key` = P2.KEY   // inner 可选

// 方法3
SELECT
	p1.KEY 
FROM
	`table_1` AS p1 
WHERE
	p1.KEY IN (SELECT p2.key FROM table_2 as p2)

查询两张表中table_1独有的部分

// 方法1
SELECT
	p1.KEY,
	p2.key
FROM
	`table_1` AS p1
	left JOIN table_2 AS P2 ON P1.`key` = P2.KEY 
	WHERE p2.key is   null 
// 方法2
SELECT
	p1.KEY 
FROM
	`table_1` AS p1 
WHERE
	p1.KEY NOT IN (SELECT p2.key FROM table_2 as p2)

查询table_1 与 table_2 的并集

	SELECT
		p1.KEY 
	FROM
		`table_1` AS p1
		LEFT JOIN table_2 AS P2 ON P1.`key` = P2.KEY
UNION
	SELECT
		p2.KEY 
	FROM
		`table_1` AS p1
		RIGHT JOIN table_2 AS P2 ON P1.`key` = P2.KEY

去除table_1与table_2 的公共部分

SELECT
	p1.KEY 
FROM
	`table_1` AS p1
	LEFT JOIN table_2 AS P2 ON P1.`key` = P2.KEY 
WHERE
	p2.KEY IS NULL
	
UNION 

SELECT
	p2.KEY 
FROM
	`table_1` AS p1
	RIGHT JOIN table_2 AS P2 ON P1.`key` = P2.KEY 
WHERE
	p1.KEY IS NULL

查询三张表中table_1中独有的

	// 方法1
SELECT
	p1.KEY ,
	p2.key
FROM
	`table_1` AS p1
	LEFT JOIN table_2 AS P2 ON P1.`key` = P2.KEY 
	LEFT JOIN table_3 AS P3 ON P1.`key` = P3.KEY 
WHERE
	p2.KEY IS NULL
	and  p3.KEY IS NULL

// 方法2
SELECT
	a.KEY 
FROM
	(
SELECT
	p1.KEY 
FROM
	`table_1` AS p1
	LEFT JOIN table_2 AS P2 ON P1.`key` = P2.KEY 
WHERE
	p2.KEY IS NULL 
	) AS a 
WHERE
	a.KEY NOT IN ( SELECT p3.KEY FROM table_3 AS p3 )

4、锁

1、共享锁(读锁)

S锁:用于不更改或不更新数据的操作(只读操作),例如 SELECT 语句
若事务 T 对数据A 加上共享锁,则其他事务只能对A加共享锁,不能加排他锁。
获得共享锁的事务只能读数据,不能修改数据
执行语句后面加上lock in share mode就代表对某些资源加上共享锁。

2、排他锁

X锁:用与数据修改操作,例如INSERT、UPDATE、DELETE语句 确保不会在同时对一资源惊吓多重更新
若事务T 对数据 A 加上排他锁,则其他事务不能在对A加任何类型的封锁。获得排他锁的事务既能读取数据,又能修改数据
操作数据库的时候,可能由于并发问题而引起数据的不一致(数据冲突)

3、 乐观锁

乐观锁不是数据库自带的,需要我们自己去实现。乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突,在操作数据时,并不进行任何其他的特殊处理(也就是不加锁),而在进行更新后,再去判断是否有冲突了。
实现方法:
1、先给数据表加一个版本字段 Version
2、每次操作时,将指定的记录的版本号 +1
3、在并发情况下,SELECT出的版本号都可能会是同一个
4 、在更新时、先判断版本Version值是否相同
5、若相同,则执行更新操作,此时添加行级锁,更新成功,解锁,Version+1;若不同则说明这段期间已经有其他程序对其进行操作了,则不进行更新操作。
更深刻的理解

4、悲观锁

悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过获取锁才能进行对相同数据的操作,所以悲观锁需要耗费较多的时间。另外与乐观锁相对应的,悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了。
共享锁和排它锁是悲观锁的不同的实现,它俩都属于悲观锁的范畴。
详细介绍

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值