awk从放弃到入门(10):awk内置函数 1https://www.zsythink.net/archives/2113 这篇文章中的知识点是建立在前文的基础上的,如果你还没有掌握前文中的知识,请先参考之前的文章。 注:在阅读这篇文章之前,最好已经了解了一些开发的基本语法,比如,函数的基本概念 等,否则在阅读时 有可能遇到障碍。 在awk中,可以自定义函数,也有内置的函数,今天我们就来总结一些常用的内置函数。 awk的内置函数大致可以分类为算数函数、字符串函数、时间函数、其他函数等,此处只总结一下个人觉得常用的函数。 算数函数 最常用的算数函数有rand函数、srand函数、int函数。 可以使用rand函数生成随机数,但是使用rand函数时,需要配合srand函数,否则rand函数返回的值将一直不变,示例如下。 可以看到,如果单纯的使用rand函数,生成的值是不变的,可以配合srand函数,生成一个大于0小于1的随机数,示例如下 可以看到,上图中生成的随机数都是小于1的小数,如果我们想要生成整数随机数,可以将上述生成的随机数乘以100,然后截取整数部分,使用int函数可以截取整数部分的值,示例如下 经过上述处理以后,可以得到一个小于100的随机整数。 字符串函数 我们可以使用gsub函数或sub函数替换某些文本,先来 看看gsub函数怎样使用。 如果我们想要将如下文本中的第一列中的小写字母”l”都替换成大写字母”L”,则可以使用gsub函数,示例如下。 如上图所示,我们使用gsub函数,将小写字母”l”替换成大写字母”L”,但是替换的范围只限于”$1″,所以,当我们再次输出文本时,发现只有文本中的第一列中的小写字母”l”被替换成了大写字母”L”,其他列中的小写字母”l”并未被替换,当然,如果你想要替换文本中所有的小写字母”l”,则可以将上图中的”$1″换成”$0″,或者省略gsub函数中的第三个参数,省略gsub中的第三个参数时,默认为”$0″,示例如下。 看完上述示例,我想你应该已经明白了gsub函数的作用,没错,gsub函数会在指定范围内查找指定的字符,并将其替换为指定的字符串。 其实,我们还可以根据正则表达式,替换字符串,示例如下。 好了,经过上述示例,你应该已经明白gsub的用法了。 那么sub函数与gsub函数有什么不同呢?我们来对比一下。 细心如你一定已经发现了,当使用gsub函数时,gsub会替换指定范围内的所有符合条件的字符。 而使用sub函数则不同,当使用sub函数时,sub函数只会替换指定范围内第一次匹配到的符合条件的字符。 我们可以把gsub函数的作用理解为指定范围内的全局替换。 可以把sub函数的作用理解为指定范围内的单次替换,只替换第一次匹配到的字符。 这就是sub函数与gsub函数的为唯一的不同之处。 我们可以通过length函数,获取到指定字符串的长度,示例如下 如上图所示,我们输出了文本中每个单词的长度,其实,length函数可以省略传入的参数,即不指定任何字符换,当省略参数时,默认使用”$0″作为参数,示例如下。 正如上图所示,我们使用length函数,获取到了文本中每一行的长度。 我们可以使用index函数,获取到指定字符位于整个字符串中的位置,示例如下 上图中,我们使用index函数,在每一行中咋找字符串”Lee”,如果Lee存在于当前行,则返回字符串Lee位于当前行的位置,如果Lee不存在于当前行,则返回0,表示当前行并不存在Lee,如上图所示,第二行中包含Lee,而且Lee位于第二行的第7个字符的位置,所以返回数字7。 在前文中,我们在总结数组时,提到过一个函数,借助这个函数可以动态的生成数组,而不用手动的设置数组中每个元素的值,没错,这个函数就是split函数。通过split函数,我们可以将指定的字符串按照指定的分割符切割,将切割后的每一段赋值到数组的元素中,从而动态的创建数组,示例如下。 如上图所示,我们通过split函数,将字符串ts切割了,以”:”作为分割符,将分割后的字符串保存到了名为huluwa的数组中,当我们输出数组中的元素时,每个元素的值为分割后的字符,其实,split函数也有对应的返回值,其返回值就是分割以后的数组长度,示例如下。 注意,被split函数分割后的数组的元素下标从1开始,不像其他语言中的数组下标是从0开始的,而且数组中元素输出的顺序可能与字符串中字符的顺序不同,原因在前文中已经说过了,如果我们想要按照顺序输出数组中的元素,可以使用如下方法。 我们先使用了split函数生成了数组,并且将split的返回值保存在变量arrlen中,然后利用for循环中变量的递增,顺序的输出了数组中的对应下标以及元素值,如果你不明白为什么,请参考前文。 其他函数 我们还能够通过asort函数根据元素的值进行排序,但是,经过asort函数排序过后的数组的下标将会被重置,示例如下 如上图所示,数组中元素的值均为数字,但是下标为自定义的字符串,通过asort函数对数组排序后,再次输出数组中的元素时,已经按照元素的值的大小进行了排序,但是,数组的下标也被重置为了纯数字,其实,asort还有一种用法,就是在对原数组元素值排序的同时,创建一个新的数组,将排序后的元素放置在新数组中,这样能够保持原数组不做任何改变,我们只要打印新数组中的元素值,即可输出排序后的元素值,示例如下。 其实,asort函数也有返回值,它的返回值就是数组的长度,换句话说,asort的返回值就是数组中元素的数量,示例如下。 理解完asort 函数,我们来认识一下asorti 函数,仔细看,是 asort 与 asorti 使用asort 函数可以根据元素的值进行排序,而使用asorti 函数可以根据元素的下标进行排序。 当元素的下标为字符串时,我们可以使用asorti 函数,根据下标的字母顺序进行排序,当元素的下标为数字时,我们就没有必要使用函数排序了,直接使用for循环即可排序,所以,此刻我们只考虑数组的下标为字符串时,怎样通过asorti 函数根据下标对数组进行排序。 当数组的下标为字符串时,asorti 函数会根据原数组中的下标的字母顺序进行排序,并且将排序后的下标放置到一个新的数组中,并且asorti函数会返回新的数组的长度,示例如下 […]
Author Archives: Administrator
mysql/mariadb知识点总结(25):二进制日志 1https://www.zsythink.net/archives/1286 这篇文章总结了mysql中二进制日志的知识点。 在本博客中,”mysql”是一个系列文章,这些文章主要对mysql/mariadb的常用知识点进行了总结,每一篇博客总结的知识点有所不同,具体内容可参考mysql文章列表。 mysql文章列表直达链接:mysql知识点总结 此处先概念性的描述一下二进制日志,然后再通俗的解释它。 在mysql中,我们称二进制日志为binlog,它记录了所有修改了数据库的语句,或者有可能会改变数据库的语句,换句话说,select、show这种不修改数据库的操作,二进制日志是不会进行记录的,二进制日志主要用于时间点恢复(备份恢复),以及主从复制结构。 二进制日志相关概念 我们先聊聊binlog是怎样用于时间点恢复的。 假如我们每天晚上12点进行一次数据库备份,此处不考虑数据量,备份时间等其他因素,那么在本次备份完成后到下次备份开始前的这段时间段中,如果数据库服务崩溃了,我们应该怎样恢复呢? 如果我们只依靠上一次的数据库备份进行恢复,那么我们最多只能恢复到上一个12点时的数据,但是12点以后的数据则会丢失,所以,我们还需要依靠二进制日志(binlog),我们先用上一次的备份将数据库恢复至最近一次12点时的样子,再利用binlog,将12点之后的所有操作”重放”一遍,由于上次备份之时到数据库崩溃之时之间的所有操作完完全全的重新执行了一遍,所以我们可以将数据库中的数据恢复至崩溃之时的样子,而不至于丢失数据,这就是binlog用于恢复时的作用,如果你使用过oracle,那么你肯定会认为,mysql中的binlog与oracle中的归档日志特别像,其实它们存在的目的都是差不多的。 我们对binlog已经有了初步的概念,我们已经知道,binlog记录了所有的修改了数据库的语句,那么,我们来想一个问题,假设,我们在执行某条修改数据库的语句时,用到了user()函数,那么当我们执行这条语句时,语句根据当前用户的信息修改了数据库,然后这条语句将被记录到binlog中,但是,语句被记录在binlog中时,并没有记录当前用户的信息,而是记录了”user()”这个函数本身的几个字符,当我们根据binlog再次重放这条语句时,如果重放这条语句的用户与这条语句被记录时所使用的用户不同,那么语句执行后的结果就不同,这样就导致根据binlog重放操作时,并不能得到与我们预想的完全一致的数据,这种情况在数据恢复时是不允许的,在主从复制时也不是我们期望看到的,所以,为了能够完全的还原日志被记录时的操作,我们应该记录对应语句到底修改了哪些行,并且记录对应语句对这些行进行了哪些修改,只有这样,才能保证我们在重放binlog时,执行的操作与记录日志时的操作是完全一致的,这样是安全了,但是,我们设想一下,如果我们执行了一条update语句,这条update语句涉及到10000行数据的修改,那么,我们就需要将这条sql涉及到的10000行数据修改都记录到binlog中,以便重放二进制日志时,能够还原当时的操作,这样与只记录一条update语句来说,记录的信息量就大的多了,这样想想,这两种记录方式还是各有优势的。当然,到底是让binlog以记录语句的模式进行记录,还是以记录数据修改的模式进行记录,这些都是数据库管理员可以决定的,我们可以设置mysql通过哪种模式记录binlog,mysql中,有三种模式,statement、row、mixed,我们来总结一下binlog的这三种记录模式。 二进制日志有3种记录方式,三种方式如下: statement模式:记录对数据库做出修改的语句,比如,update A set test=’test’,如果使用statement模式,那么这条update语句将会被记录到二进制日志中,使用statement模式时,优点是binlog日志量少,IO压力小,性能较高,缺点是为了能够尽量的完全一致的还原操作,除了记录语句本身以外,可能还需要记录一些相关的信息,而且,在使用一些特定的函数时,并不能保证恢复操作与记录时完全一致。 row模式:记录对数据库做出修改的语句所影响到的数据行以及这些行的修改,比如,update A set test=’test’,如果使用row模式,那么这条update语句所影响到的行所对应的修改,将会记录到binlog中,比如,A表中有1000条数据,那么当执行这条update语句以后,由于1000条数据都会被修改,所以会有1000行数据被记录到二进制日志中,以及它们是怎样被修改的,使用row模式时,优点是能够完全的还原或者复制日志被记录时的操作,缺点是记录日志量较大,IO压力大,性能消耗较大。 mixed模式:混合使用上述两种模式,一般的语句使用statment方式进行保存,如果遇到一些特殊的函数,则使用row模式进行记录,这种记录方式被称之为mixed,看上去这种方式似乎比较美好,但是在生产环境中,为了保险起见,一般会使用row模式。 管理员可以使用binlog_format变量设置二进制日志的记录方式,为了使配置永久生效,我们可以在my.cnf配置文件中加入如下配置。 binlog_format=row 上述配置表示使用row模式记录binlog 看完了上述概念以后,是不是已经对二进制日志文件有了一定的了解呢?趁热打铁,我们继续聊二进制日志,先把理论了解完了,再动手实践。 二进制日志文件,顾名思义,它是二进制的,所以我们不能直接使用cat命令进行查看,而是需要通过一些别的命令查看其内容,而且,二进制日志文件,有”事件”和”位置”的概念,什么是事件呢?通俗的讲,我们可以把binlog中的每一条记录当做一个”事件”,因为binlog记录了所有对数据库进行的修改,所以,我们可以认为,数据库的修改被记录到二进制日志中,这些记录每一条都可以理解为一个”事件”,由于二进制日志文件是二进制的,所以,我们可以把整个二进制文件想象成一个字节序列,假设,二进制日志文件刚开始是空的,从第1个字节开始记录,假设记录第一个”事件”(第一条记录),需要15个字节,那么第一个事件的开始”位置”就是1,结束”位置”就是15,由于前15个字节已经被第一个事件占用,那么当我们想要通过二进制日志记录第二个事件时,则需要从第15个字节向后开始记录,假设记录第二个”事件”需要20个字节,那么第二个事件在binlog中的起始”位置”就是15,结束”位置”就是35,以此类推,这就是二进制日志中,”事件”与”位置”的概念,”事件”被称为events,”位置”被称为position,如果你现在还不能很清晰的理解他们,没有关系,当我们动手实践的时候,你自然会明白。 二进制日志相关参数 好了,理论理解的差不多了,我们来看看与二进制日志有关的一些参数,有了之前的理论基础,再来了解他们,应该很容易了。 log_bin : 此变量用于控制是否开启二进制日志,而且这是一个只读变量,什么意思呢?咱们慢慢聊,默认情况下,当我们启动数据库以后,在当前数据库连接中查看此变量的值,此变量值可能为OFF,表示不记录二进制日志,如果想要记录二进制日志,只需将此值设置为二进制日志的文件名即可,但是需要注意的是,我们无法在当前会话中使用set命令设置log_bin的值,因为它是一个只读变量,我们只能通过修改my.cnf的方式,设置log_bin的值,假设,我们编辑my.cnf文件,设置log_bin的值为mybinlog,那么,在mysql的数据目录中,将会自动生成一个以mybinlog为文件名前缀的二进制日志文件,如果想要再次禁用binlog,只需要将log_bin这一行配置从my.cnf文件中注释即可,或者将其删除,重启mysql服务后,再次查看log_bin的值,其值为OFF,注意,不要直接在my.cnf文件中将log_bin的值设置为ON或者OFF,如果这样做,你将会看到以ON或者OFF为文件名前缀的二进制日志文件。换句话说,如果my.cnf配置文件中没有log_bin的配置,则表示未开启二进制日志,如果my.cnf中存在log_bin的配置,那么则表示开启了二进制日志,同时二进制日志文件的名称将会以log_bin对应的值为文件名前缀,同时,二进制日志文件的后缀名会进行自动编号,每次日志滚动后,后缀名编号自动加1。 sql_log_bin :此变量用于标识当前会话中的操作是否会被记录于二进制日志,此变量值设置为ON,则表示在当前数据库连接中,对数据库进行修改的语句将会被记录到binlog中,此变量值设置为OFF,则表示在当前数据库连接中,对数据库进行的修改的语句将不会被记录到binlog中,在主从复制结构中,这些语句由于没有被binlog记录,所以也不会同步到从节点中。换句话说,即使在my.cnf配置文件中设置了log_bin的值,当前会话中,如果sql_log_bin的值设置为OFF,当前会话的操作也不会记录在二进制日志中。而且需要注意的是,sql_log_bin是一个会话界别的变量,只能在当前会话中使用set sql_log_bin命令进行设置,不能使用set global sql_log_bin命令进行设置,因为它是会话级别的变量,而且,sql_log_bin也不能配置在my.cnf文件中,否则可能会无法启动mysql。 binlog_format : 此变量值得含义上文已经解释过,此变量的值决定了二进制日志的记录方式,此变量的值可以设置为statement、row、mixed,分别表示以语句的形式记录二进制日志,以数据修改的形式记录二进制日志,以混合的方式记录二进制日志,安全保险起见,推荐使用row的方式记录。 max_binlog_size :设置单个二进制日志文件的最大大小,以字节为单位,超过此值大小,则二进制日志文件会自动滚动,比如设置为500M为524288000。 sync_binlog :还记的我们总结的事务日志的相关文章吗?当我们把innodb_flush_log_at_trx_commit设置为1的时候,表示事务提交时,事务日志立马从内存刷写到磁盘中的事务日志文件中,而sync_binlog对于二进制日志的作用,就像innodb_flush_log_at_trx_commit对于事务日志的作用,由于二进制日志一开始存在于内存(binlog_cache)中,如果将sync_binlog设置为1,则表示每1次事务提交之后,都会立即将内存中的二进制日志立即同步到磁盘中的二进制日志文件中,如果将sync_binlog设置为0,则表示当事务提交之后,mysql不会立即将内存中的binlog刷写到磁盘中的binlog日志文件中,而是由文件系统决定什么时候刷写,这可能取决于文件系统的缓存机制,当此值设置为0时,一旦操作系统宕机,那么将丢失未从内存中同步到磁盘中的binlog,所以,当此值设置为0时,安全性最差,但是性能最高,当此值设置为1时,安全性最高,性能最差,除了将此值设置为0或1,还能设置为N,假设将此值设置为3,则表示每3次事务提交后,将binlog从内存刷写到磁盘一次,值设置的越大,有可能丢失的日志数据将会越多,当然,性能会越好,在追求安全的情况下,推荐设置为1,但是听说,此值设置为0和设置为1时在性能上的差距还是比较明显的,如果设置为0或N,最好为操作系统准备带有备用电源的缓存。 实践 说了这么多理论,我们来动手实践一下,在实践中,在回过头来看刚才的理论,会更加明了。 默认情况下,二进制日志可能未开启,查询如下 我们可以手动修改my.cnf文件,在[mysqld]配置段中加入如下配置,表示开启binlog,并且设置二进制日志文件名前缀为mybinlog。 重启mysql服务后,再次查看log_bin的值,可以看出,二进制日志功能已经开启。 查看对应的数据文件目录,发现其中已经存在了以mybinlog开头的二进制日志文件,默认编号从000001开始,而且能看到一个名为mybinlog.index的文件,这个文件的作用我们一会再说。 回到mysql的命令行下,使用如下两条命令中的任何一条,均可在mysql中查看二进制日志的文件列表 show binary logs; show […]