@lifei6671
2019-11-27T04:23:45.000000Z
字数 15839
阅读 321
$GLOBALS$_SERVER$_GET$_POST$_FILES$_COOKIE$_SESSION$_REQUEST$_ENV
require 和 include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时产生 E_COMPILE_ERROR 级别的错误。换句话说将导致脚本中止而 include 只产生警告(E_WARNING),脚本会继续运行
include_once 语句在脚本执行期间包含并运行指定文件。此行为和 include 语句类似,唯一区别是如果该文件中已经被包含过,则不会再次包含。如同此语句名字暗示的那样,只会包含一次
<?php$f = 0.58;var_dump(intval($f * 100)); //为啥输出57?>
这里的关键点就在于, 小数在二进制的表示, 关于小数如何用二进制表示,:
将该数字乘以2,取出整数部分作为二进制表示的第1位;然后再将小数部分乘以2,将得到的整数部分作为二进制表示的第2位;以此类推,知道小数部分为0。
特殊情况: 小数部分出现循环,无法停止,则用有限的二进制位无法准确表示一个小数,这也是在编程语言中表示小数会出现误差的原因
下面我们具体计算一下0.6的小数表示过程
0.6 * 2 = 1.2 ——————- 10.2 * 2 = 0.4 ——————- 00.4 * 2 = 0.8 ——————- 00.8 * 2 = 1.6 ——————- 10.6 * 2 = 1.2 ——————- 1…………
class Config {private static $instance = null;private function __construct(){}private function __clone(){}public static function getInstance() {if self::$instance == null {self::$instance = new self();}return self::$instance;}}
PHP变量的内存管理通过引用计数机制实现,当变量赋值、传递时并不会直接硬拷贝,而是增加value的引用数,unset、return等释放变量时再减掉引用数,减掉后如果发现refcount变为0则直接释放value,这是变量的基本gc过程,PHP正是通过这个机制实现的自动垃圾回收,但是有一种情况是这个机制无法解决的,从而因变量无法回收导致内存始终得不到释放,这种情况就是循环引用,简单的描述就是变量的内部成员引用了变量自身,比如数组中的某个元素指向了数组,这样数组的引用计数中就有一个来自自身成员,试图释放数组时因为其refcount仍然大于0而得不到释放,而实际上已经没有任何外部引用了,这种变量不可能再被使用,所以PHP引入了另外一个机制用来处理变量循环引用的问题。
一个变量只能加入一次buffer,为了防止重复加入,变量加入后会把zend_refcounted_h.gc_info置为GC_PURPLE,即标为紫色,下次refcount减少时如果发现已经加入过了则不再重复插入。垃圾缓存区是一个双向链表,等到缓存区满了以后则启动垃圾检查过程:遍历缓存区,再对当前变量的所有成员进行遍历,然后把成员的refcount减1(如果成员还包含子成员则也进行递归遍历,其实就是深度优先的遍历),最后再检查当前变量的引用,如果减为了0则为垃圾。这个算法的原理很简单,垃圾是由于成员引用自身导致的,那么就对所有的成员减一遍引用,结果如果发现变量本身refcount变为了0则就表明其引用全部来自自身成员。具体的过程如下:
(1) 从buffer链表的roots开始遍历,把当前value标为灰色(zend_refcounted_h.gc_info置为GC_GREY),然后对当前value的成员进行深度优先遍历,把成员value的refcount减1,并且也标为灰色;
(2) 重复遍历buffer链表,检查当前value引用是否为0,为0则表示确实是垃圾,把它标为白色(GC_WHITE),如果不为0则排除了引用全部来自自身成员的可能,表示还有外部的引用,并不是垃圾,这时候因为步骤(1)对成员进行了refcount减1操作,需要再还原回去,对所有成员进行深度遍历,把成员refcount加1,同时标为黑色;
(3) 再次遍历buffer链表,将非GC_WHITE的节点从roots链表中删除,最终roots链表中全部为真正的垃圾,最后将这些垃圾清除。
在PHP文档里,有时会看到“二进制安全的”这样的描述,基本就是这么一个意思:类似的功能,在C语言里的函数会对有些字符进行特别处理,而PHP这个函数对于所有字符一视同仁,不用担心会有特殊字符影响处理,特别不用担心编码0字符。
PHP里,有string的概念。string里,每个字符的类型为byte(与PHP相比,Java的每个字符为Character,是UTF8字符,C语言的每个字符可以在编译时选择)。
byte里,有ASCII代码的字符,例如ABC,123,abc,也有一些特殊字符,例如回车,退格之类的。
特殊字符很多是不能显示的。或者说,他们的显示方式没有标准,例如编码65到哪儿都是字母A,编码97到哪儿都是字符a。而退格键却在有的地方显示成一个符号,在有的地方就会真的把前一个字符退掉。
PHP以C为基础,所以很多描述都是以C为对比。C的字符串里,一种经典的定义就是,以编码0作为字符串的结尾。那么,假设这样一个string,里面3个字符的编码分别是97,0,97。那么,C里面如果有str_replace等效的函数, 利用它把97换成98,那么这个函数读取到0的时候,就认为已经结束了,就会得到98,0,97,这就是“二进制不安全”。跟它对应的,PHP里的str_replace是二进制安全的,那么这个0不会被视为特殊的结束符号,于是结果就是98,0,98,这是我们期望的结果。
__DIR__ //当前脚本目录__LINE__ //当前行数__METHOD__ //当前执行的方法__FUNCTION__ //当前执行的函数名__CLASS__ //当前执行的类__FILE__ //当前执行的脚本名称__NAMESPACE__ //当前的命名空间__TRAIT__ //当前的代码片段
/*** 反转数组* @param array $arr* @return array*/function reverse($arr){$n = count($arr);$left = 0;$right = $n - 1;while ($left < $right) {$temp = $arr[$left];$arr[$left++] = $arr[$right];$arr[$right--] = $temp;}return $arr;}
/*** 寻找两个有序数组里相同的元素* @param array $arr1* @param array $arr2* @return array*/function find_common($arr1, $arr2){$common = array();$i = $j = 0;$count1 = count($arr1);$count2 = count($arr2);while ($i < $count1 && $j < $count2) {if ($arr1[$i] < $arr2[$j]) {$i++;} elseif ($arr1[$i] > $arr2[$j]) {$j++;} else {$common[] = $arr[$i];$i++;$j++;}}return array_unique($common);}
/*** 打乱数组* @param array $arr* @return array*/function custom_shuffle($arr){$n = count($arr);for ($i = 0; $i < $n; $i++) {$rand_pos = mt_rand(0, $n - 1);if ($rand_pos != $i) {$temp = $arr[$i];$arr[$i] = $arr[$rand_pos];$arr[$rand_pos] = $temp;}}return $arr;}4.给一个有数字和字母的字符串,让连着的数字和字母对应#function number_alphabet($str){$number = preg_split('/[a-z]+/', $str, -1, PREG_SPLIT_NO_EMPTY);$alphabet = preg_split('/\d+/', $str, -1, PREG_SPLIT_NO_EMPTY);$n = count($number);for ($i = 0; $i < $count; $i++) {echo $number[$i] . ':' . $alphabet[$i] . '</br>';}}$str = '1a3bb44a2ac';number_alphabet($str);//1:a 3:bb 44:a 2:ac
思路:
代码如下:
/*** 求n内的质数* @param int $n* @return array*/function get_prime($n){$prime = array(2);//2为质数for ($i = 3; $i <= $n; $i += 2) {//偶数不是质数,步长可以加大$sqrt = intval(sqrt($i));//求根号nfor ($j = 3; $j <= $sqrt; $j += 2) {//i是奇数,当然不能被偶数整除,步长也可以加大。if ($i % $j == 0) {break;}}if ($j > $sqrt) {array_push($prime, $i);}}return $prime;}print_r(getPrime(1000));
相关题目:一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数, 再数到第m只,在把它踢出去…,如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。
/*** 获取大王* @param int $n* @param int $m* @return int*/function get_king_mokey(int $n,int $m){$arr = range(1, $n);//创建N个元素的数组$i = 0;while (count($arr) > 1) { //不断的循环$i++;$survice = array_shift($arr); //队首的出队if ($i % $m != 0) { //如果不符合第m个则再入队array_push($arr, $survice);}}return $arr[0];}
思路:假设最前面的1000个数为最小的,算出这1000个数中最大的数,然后和第1001个数比较,如果这最大的数比这第1001个数小的话跳过,如果要比这第1001个数大则将两个数交换位置,并算出新的1000个数里面的最大数,再和下一个数比较,以此类推。
代码如下:
//寻找最小的k个数//题目描述//输入n个整数,输出其中最小的k个。/*** 获取最小的k个数* @param array $arr* @param int $k [description]* @return array*/function get_min_array($arr, $k){$n = count($arr);$min_array = array();for ($i = 0; $i < $n; $i++) {if ($i < $k) {$min_array[$i] = $arr[$i];} else {if ($i == $k) {$max_pos = get_max_pos($min_array);$max = $min_array[$max_pos];}if ($arr[$i] < $max) {$min_array[$max_pos] = $arr[$i];$max_pos = get_max_pos($min_array);$max = $min_array[$max_pos];}}}return $min_array;}/*** 获取最大的位置* @param array $arr* @return array*/function get_max_pos($arr){$pos = 0;for ($i = 1; $i < count($arr); $i++) {if ($arr[$i] > $arr[$pos]) {$pos = $i;}}return $pos;}$array = [1, 100, 20, 22, 33, 44, 55, 66, 23, 79, 18, 20, 11, 9, 129, 399, 145, 2469, 58];$min_array = get_min_array($array, 10);print_r($min_array);
代码如下:
/*** 二分查找* @param array $array 数组* @param int $n 数组数量* @param int $value 要寻找的值* @return int*/function binary_search($array, $n, $value){$left = 0;$right = $n - 1;while ($left <= $right) { //只要没有重合就一直循环$mid = intval(($left + $right) / 2); //需要知道两个区间的中间值if ($value > $array[$mid]) { //跟中间值比较大小$right = $mid + 1; //如果比中间值大,说明在左侧,这个跟数组的排序有关} elseif ($value < $array[$mid]) {$left = $mid - 1;} else {return $mid;}}return -1;}
思路:二分查找
/*** 获取绝对值最小的元素* @param array $arr* @return int*/function get_min_abs_value($arr){$n = count($arr);//如果符号相同,直接返回if (is_same_sign($arr[0], $arr[$n - 1])) {return $arr[0] >= 0 ? $arr[0] : $arr[$n - 1];}//二分查找$left = 0;$right = $n - 1;while ($left <= $right) {if ($left + 1 === $right) {return abs($arr[$left]) < abs($arr[$right]) ? $arr[$left] : $arr[$right];}$mid = intval(($left + $right) / 2);if ($arr[$mid] < 0) {$left = $mid + 1;} else {$right = $mid - 1;}}}/*** 判断符号是否相同* @param int $a* @param int $b* @return boolean*/function is_same_sign($a, $b){if ($a * $b > 0) {return true;} else {return false;}}
思路:动态规划
function three_sum($arr){$n = count($arr);$return = array();for ($i=0; $i < $n; $i++) {$left = $i + 1;$right = $n - 1;while ($left <= $right) {$sum = $arr[$i] + $arr[$left] + $arr[$right];if ($sum < 0) {$left++;} elseif ($sum > 0) {$right--;} else {$numbers = $arr[$i] . ',' . $arr[$left] . ',' . $arr[$right];if (!in_array($numbers, $return)) {$return[] = $numbers;}$left++;$right--;}}}return $return;}$arr = [-10, -9, -8, -4, -2, 0, 1, 2, 3, 4, 5, 6, 9];var_dump(three_sum($arr));
思路:动态规划
/*** 获取最大的连续和* @param array $arr* @return int*/function max_sum_array($arr){$currSum = 0;$maxSum = 0;//数组元素全为负的情况,返回最大数$n = count($arr);for ($i = 0; $i < $n; $i++) {if ($currSum >= 0) {$currSum += $arr[$i];} else {$currSum = $arr[$i];}}if ($currSum > $maxSum) {$maxSum = $currSum;}return $maxSum;}
时间复杂度:O(NlogN) 稳定性:不稳定
function quickSort($arr) {$len = count($arr);if ($len <= 1){return $arr;}$base = $arr[0];$left = [];$right = [];for($i=1;$i < $len;$i++) {if ($arr[$i] > $base) {$left[] = $arr[$i];} else {$right[] = $arr[$i];}}$left = quickSort($left);$right = quickSort($right);return array_merge($left,[$base],$right);}
时间复杂度:O(N2) 稳定性:稳定
function bubbleSort($arr) {$len = count($arr);if ($len <= 1){return $arr;}for($i = 0;$i < $len -1; $i++) {for($j = 0;$j < $len -1 - $i;$j++) {if($arr[$j] > $arr[$j+1]) {$temp = $arr[$j];$arr[$j] = $arr[$j + 1];$arr[$j + 1] = $temp;}}}}
时间复杂度:O(n^2) 稳定性:不稳定
function simpleSelectSort($arr){$len = count($arr);if($len <= 1){return $arr;}for ($i = 0;$i < $len - 1; $i++) {$index = $i; //记录当前索引//遍历当前索引之后的数组,来查找最小值for ($j = $i + 1; $j < $len; $j ++) {//如果存在则记录最小值的索引if ($arr[$index] > $arr[$j]) {$index = $j;}}//如果是当前索引,则不用交换if($index != $i) {$temp = $arr[$index];$arr[$index] = $arr[$i];$arr[$i] = $temp;}}return $arr;}
时间复杂度:O(n^2) 空间复杂度:O(1) 稳定性:稳定
//插入排序function insert_sort($arr) {//获取数组单元个数$count = count($arr);//外层循环用于从未排序区域中取出待排序元素for ($i=1; $i < $count; $i++) {//获取当前需要插入已排序区域的元素值$temp = $arr[$i];//内层循环用于从已排序区域寻找待排序元素的插入位置for ($j=$i-1; $j >= 0; $j--) {//如果$arr[$i]比已排序区域的$arr[$j]小,就后移$arr[$j]if ($temp < $arr[$j]) {$arr[$j+1] = $arr[$j];$arr[$j] = $temp;} else {//如果$arr[$i]不小于$arr[$j],则对已排序区无需再排序break;}}}return $arr;}

事务是基于重做日志文件(redo log)和回滚日志(undo log)实现的。
每提交一个事务必须先将该事务的所有日志写入到重做日志文件进行持久化,数据库就可以通过重做日志来保证事务的原子性和持久性。
每当有修改事务时,还会产生undo log,如果需要回滚,则根据undo log 的反向语句进行逻辑操作,比如insert 一条记录就delete 一条记录。undo log 主要实现数据库的一致性,还可以用来实现MVCC。
事务主要分为:
MySQL主要有两个数据库引擎:myisam 和 Innodb.
主要区别如下:
MyISAM:
myisam只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。也可以通过lock table命令来锁表,这样操作主要是可以模仿事务,但是消耗非常大,一般只在实验演示中使用。
InnoDB :
Innodb支持事务和行级锁,是innodb的最大特色。
事务的ACID属性:atomicity,consistent,isolation,durable。
并发事务带来的几个问题:更新丢失,脏读,不可重复读,幻读。
事务隔离级别:未提交读(Read uncommitted),已提交读(Read committed),可重复读(Repeatable read),可序列化(Serializable)
四种隔离级别的比较
| 读数据一致性及并发副作用 隔离级别 | 读数据一致性 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|---|
| 为提交读(read uncommitted) | 最低级别,不读物理上顺坏的数据 | 是 | 是 | 是 |
| 已提交读(read committed) | 语句级 | 否 | 是 | 是 |
| 可重复读(Repeatable red) | 事务级 | 否 | 否 | 是 |
| 可序列化(Serializable) | 最高级别,事务级 | 否 | 否 | 否 |
查看mysql的默认事务隔离级别 show global variables like ‘tx_isolation’;.
Innodb的行锁模式有以下几种:共享锁,排他锁,意向共享锁(表锁),意向排他锁(表锁),间隙锁。
注意:当语句没有使用索引,innodb不能确定操作的行,这个时候就使用的意向锁,也就是表锁
关于死锁:
什么是死锁?当两个事务都需要获得对方持有的排他锁才能完成事务,这样就导致了循环锁等待,也就是常见的死锁类型。
解决死锁的方法:
MyISAM :
myisam属于堆表
myisam在磁盘存储上有三个文件,每个文件名以表名开头,扩展名指出文件类型。
myisam表还支持三种不同的存储格式:
InnoDB :
innodb属于索引组织表
innodb有两种存储方式,共享表空间存储和多表空间存储
两种存储方式的表结构和myisam一样,以表名开头,扩展名是.frm。
如果使用共享表空间,那么所有表的数据文件和索引文件都保存在一个表空间里,一个表空间可以有多个文件,通过innodb_data_file_path和innodb_data_home_dir参数设置共享表空间的位置和名字,一般共享表空间的名字叫ibdata1-n。
如果使用多表空间,那么每个表都有一个表空间文件用于存储每个表的数据和索引,文件名以表名开头,以.ibd为扩展名。
myisam引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。
innodb引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列。
myisam允许没有任何索引和主键的表存在,
myisam的索引都是保存行的地址。
innodb引擎如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见)
innodb的数据是主索引的一部分,附加索引保存的是主索引的值。
myisam保存有表的总行数,如果select count(*) from table;会直接取出出该值
innodb没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。
myisam支持 FULLTEXT类型的全文索引
innodb不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。(sphinx 是一个开源软件,提供多种语言的API接口,可以优化mysql的各种查询)
使用这条命令时,innodb不会从新建立表,而是一条一条的删除数据,在innodb上如果要清空保存有大量数据的表,最好不要使用这个命令。(推荐使用truncate table,不过需要用户有drop此表的权限)
myisam的索引以表名+.MYI文件分别保存。
innodb的索引和数据一起保存在表空间里。
插入缓冲(Insert Buffer/Change Buffer):提升插入性能,change buffering是insert buffer的加强,insert buffer只针对insert有效,change buffering对insert、delete、update(delete+insert)、purge都有效
只对于非聚集索引(非唯一)的插入和更新有效,对于每一次的插入不是写到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,如果在则直接插入;若不在,则先放到Insert Buffer 中,再按照一定的频率进行合并操作,再写回disk。这样通常能将多个插入合并到一个操作中,目的还是为了减少随机IO带来性能损耗。
Doublewrite缓存是位于系统表空间的存储区域,用来缓存InnoDB的数据页从innodb buffer pool中flush之后并写入到数据文件之前,所以当操作系统或者数据库进程在数据页写磁盘的过程中崩溃,Innodb可以在doublewrite缓存中找到数据页的备份而用来执行crash恢复。数据页写入到doublewrite缓存的动作所需要的IO消耗要小于写入到数据文件的消耗,因为此写入操作会以一次大的连续块的方式写入
在应用(apply)重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是double write
doublewrite组成:
doublewrite buffer,大小2M。对缓冲池的脏页进行刷新时,不是直接写磁盘,而是会通过memcpy()函数将脏页先复制到内存中的doublewrite buffer,之后通过doublewrite 再分两次,每次1M顺序地写入共享表空间的物理磁盘上,在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大。在完成doublewrite页的写入后,再将doublewrite buffer 中的页写入各个 表空间文件中,此时的写入则是离散的。如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,innodb可以从共享表空间中的doublewrite中找到该页的一个副本,将其复制到表空间文件,再应用重做日志。
Adaptive Hash index属性使得InnoDB更像是内存数据库。该属性通过innodb_adapitve_hash_index开启,也可以通过—skip-innodb_adaptive_hash_index参数
关闭
Innodb存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,二级索引成为热数据,建立哈希索引可以带来速度的提升
经常访问的二级索引数据会自动被生成到hash索引里面去(最近连续被访问三次的数据),自适应哈希索引通过缓冲池的B+树构造而来,因此建立的速度很快。
哈希(hash)是一种非常快的等值查找方法,在一般情况下这种查找的时间复杂度为O(1),即一般仅需要一次查找就能定位数据。而B+树的查找次数,取决于B+树的高度,在生产环境中,B+树的高度一般3-4层,故需要3-4次的查询。
InnoDB使用两种预读算法来提高I/O性能:线性预读(linear read-ahead)和随机预读(randomread-ahead)
为了区分这两种预读的方式,我们可以把线性预读放到以extent为单位,而随机预读放到以extent中的page为单位。线性预读着眼于将下一个extent提前读取到buffer pool中,而随机预读着眼于将当前extent中的剩余的page提前读取到buffer pool中。
事务日志是通过redo和innodb的存储引擎日志缓冲(Innodb log buffer)来实现的,当开始一个事务的时候,会记录该事务的lsn(log sequence number)号; 当事务执行时,会往InnoDB存储引擎的日志的日志缓存里面插入事务日志;当事务提交时,必须将存储引擎的日志缓冲写入磁盘(通过innodb_flush_log_at_trx_commit来控制),也就是写数据前,需要先写日志。这种方式称为“预写日志方式”
针对列中的值从左往右建立索引,截的越短,重复度越高区分度越小,所以效果越不好截的越长,区分度越高,索引效果好,但是增删改慢间接影响查询速度,优先考虑在where 和orderby建立索引。
还有其它常见的就
尽可能使用更小的字段类型(因为mysql从磁盘读取数据之后是存到内存当中,这意味着更小的数据类型使得从磁盘读取或者打包到内存效率会更好)等等
通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。可以大大加快 数据的检索速度,这也是创建索引的最主要的原因。可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST没有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。
GET产生一个TCP数据包,POST产生两个TCP数据包。
在Tcp连接中,服务端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中,B端向A端发送的ACK和FIN是分两次发送的。因为在B端接收到A端的FIN后,B端可能还有数据要传输,所以先发送ACK,等B端处理完自己的事情后就可以发送FIN断开连接了。
如果设置了过期时间,Cookie存在硬盘里
没有设置过期时间,Cookie存在内存里
COOKIE保存在客户端,而SESSION则保存在服务器端
从安全性来讲,SESSION的安全性更高
从保存内容的类型的角度来讲,COOKIE只保存字符串(及能够自动转换成字符串)
从保存内容的大小来看,COOKIE保存的内容是有限的,比较小,而SESSION基本上没有这个限制
从性能的角度来讲,用SESSION的话,对服务器的压力会更大一些
SEEION依赖于COOKIE,但如果禁用COOKIE,也可以通过url传递