Cannot enlarge string buffer containing XX bytes by XX more bytes
在ELK的数据库报警系统中,发现有台机器报出了下面的错误:
2018-12-04 18:55:26.842 CST,"XXX","XXX",21106,"XXX",5c065c3d.5272,4,"idle",2018-12-04 18:51:41 CST,117/0,0,ERROR,54000,"out of memory","Cannot enlarge string buffer containing 0 bytes by 1342177281 more bytes.",,,,,,,"enlargeStringInfo, stringinfo.c:268",""
当看到是发生了OOM时,以为是整个数据库实例存在了问题,线上检查发现数据库正常,后查阅资料了解到,pg对于一次执行的查询语句长度是有限制的,如果长度超过了1G,则会报出上面的错误。
上面日志中的1342177281 bytes是查询的长度。
在使用copy的时候,也常会报出类似的问题,此时就要根据报错,查看对应的行数是不是由于引号或转义问题导致了对应行没有恰当的结束,或者是一整行的内容大于了1G。
下面是翻阅pg9.6源码找到的相关内容:
结合注释,pg的源码很容易看懂。
src/include/utils/memutils.h
/*
* MaxAllocSize, MaxAllocHugeSize
* Quasi-arbitrary limits on size of allocations.
*
* Note:
* There is no guarantee that smaller allocations will succeed, but
* larger requests will be summarily denied.
*
* palloc() enforces MaxAllocSize, chosen to correspond to the limiting size
* of varlena objects under TOAST. See VARSIZE_4B() and related macros in
* postgres.h. Many datatypes assume that any allocatable size can be
* represented in a varlena header. This limit also permits a caller to use
* an "int" variable for an index into or length of an allocation. Callers
* careful to avoid these hazards can access the higher limit with
* MemoryContextAllocHuge(). Both limits permit code to assume that it may
* compute twice an allocation's size without overflow.
*/
#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
src/backend/lib/stringinfo.c
/*
* enlargeStringInfo
*
* Make sure there is enough space for 'needed' more bytes
* ('needed' does not include the terminating null).
*
* External callers usually need not concern themselves with this, since
* all stringinfo.c routines do it automatically. However, if a caller
* knows that a StringInfo will eventually become X bytes large, it
* can save some palloc overhead by enlarging the buffer before starting
* to store data in it.
*
* NB: because we use repalloc() to enlarge the buffer, the string buffer
* will remain allocated in the same memory context that was current when
* initStringInfo was called, even if another context is now current.
* This is the desired and indeed critical behavior!
*/
void
enlargeStringInfo(StringInfo str, int needed)
{
int newlen;
/*
* Guard against out-of-range "needed" values. Without this, we can get
* an overflow or infinite loop in the following.
*/
if (needed < 0) /* should not happen */
elog(ERROR, "invalid string enlargement request size: %d", needed);
if (((Size) needed) >= (MaxAllocSize - (Size) str->len))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("out of memory"),
errdetail("Cannot enlarge string buffer containing %d bytes by %d more bytes.",
str->len, needed)));
needed += str->len + 1; /* total space required now */
/* Because of the above test, we now have needed <= MaxAllocSize */
if (needed <= str->maxlen)
return; /* got enough space already */
/*
* We don't want to allocate just a little more space with each append;
* for efficiency, double the buffer size each time it overflows.
* Actually, we might need to more than double it if 'needed' is big...
*/
newlen = 2 * str->maxlen;
while (needed > newlen)
newlen = 2 * newlen;
/*
* Clamp to MaxAllocSize in case we went past it. Note we are assuming
* here that MaxAllocSize <= INT_MAX/2, else the above loop could
* overflow. We will still have newlen >= needed.
*/
if (newlen > (int) MaxAllocSize)
newlen = (int) MaxAllocSize;
str->data = (char *) repalloc(str->data, newlen);
str->maxlen = newlen;
}
src/include/lib/stringinfo.h
下面是字符串存储用到的结构体:
/*-------------------------
* StringInfoData holds information about an extensible string.
* data is the current buffer for the string (allocated with palloc).
* len is the current string length. There is guaranteed to be
* a terminating '\0' at data[len], although this is not very
* useful when the string holds binary data rather than text.
* maxlen is the allocated size in bytes of 'data', i.e. the maximum
* string size (including the terminating '\0' char) that we can
* currently store in 'data' without having to reallocate
* more space. We must always have maxlen > len.
* cursor is initialized to zero by makeStringInfo or initStringInfo,
* but is not otherwise touched by the stringinfo.c routines.
* Some routines use it to scan through a StringInfo.
*-------------------------
*/
typedef struct StringInfoData
{
char *data;
int len;
int maxlen;
int cursor;
} StringInfoData;
typedef StringInfoData *StringInfo;
从存放字符串或二进制的结构体StringInfoData中,可以看出pg字符串类型不支持\u0000的原因,因为在pg中的字符串形式是C strings,是以\0结束的字符串,\0在ASCII中叫做NUL,Unicode编码表示为\u0000,八进制则为0x00,如果字符串中包含\0,pg会当做字符串的结束符。
pg中的字符串不支持其中包含NULL(\0x00),这个很明显是不同于NULL值的,NULL值pg是支持的。
在具体的使用中,可以将\u0000替换掉再导入pg数据库。
在其他数据库导入pg时,可以使用下面方式替换:
regexp_replace(stringWithNull, '\\u0000', '', 'g')
java程序中替换:
str.replaceAll('\u0000', '')
vim替换:
s/\x00//g;
参考:
src/backend/lib/stringinfo.c
src/include/lib/stringinfo.h
src/include/utils/memutils.h
https://en.wikipedia.org/wiki/Null-terminated_string
Cannot enlarge string buffer containing XX bytes by XX more bytes的更多相关文章
- ORA-06502:PL/SQL :numberic or value error: character string buffer too small
今天遇到一个错误提示:ORA-06502:PL/SQL :numberic or value error: character string buffer too small,一般对应的中文信息为:O ...
- String、String Buffer、String Builder
对于String.String Buffer.String Builder:我一直都只知道String是字符串常量,后两者是字符串变量: String和String Buffer是线程安全的,Stri ...
- String Buffer和String Builder(String类深入理解)
String在Java里面JDK1.8后它属于一个特殊的类,在创建一个String基本对象的时候,String会向“ 字符串常量池(String constant pool)” 进行检索是否有该数 ...
- 中文转unicode,中文转bytes,unicode转bytes java实现
utf-8 utf-8格式的中文由三位字节组成. UTF-8的编码规则很简单,只有二条: 1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码.因此对于英语字母,UTF-8编 ...
- Exception: Operation xx of contract xx specifies multiple request body parameters to be serialized without any wrapper elements.
Operation 'CreateProductCodeStock' of contract 'IChileService' specifies multiple request body param ...
- Linux内核中的Kconfig、xx.defconfig、xx.config、Makefile
什么是Kconfig.xx.defconfig.xx.config.Makefile Kconfig: 一个文本形式的文件,其中主要作用是在内核配置时候,作为配置选项. xx.deconfig: Li ...
- (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
在linux环境下配置项目运行环境时,部署的人员都会分配一下内存,以保证程序正常的运行.其实在开发的时候(window系统),就已经涉及到内存分配了,只是这些参数有默认值,因此一直没有去重视它. 以M ...
- eclipse不能自动编译XX.java为XX.classs
问题描述:eclipse不能自动编译XX.java为XX.classs 原因:今天下午写代码,因为需要引入jstl包,引入后发现原来项目中已经引入了,然后我又把包删除了,忘记删除java build ...
- Python3.x:报错POST data should be bytes, an iterable of bytes
Python3.x:报错POST data should be bytes, an iterable of bytes 问题: python3.x:报错 POST data should be byt ...
随机推荐
- Django_rest_framework_组件(authentication、permission、throttle)
认证组件 说明 from rest_framework.authentication import BaseAuthentication class TestAuthentication(BaseAu ...
- jQuery全屏滚动插件fullPage使用
1. 引入jquery.js和jquery.fullPage.min.js <script src="jquery.min.js"></script> &l ...
- DPDK网卡绑定
进入DPDK目录编译环境 # cd ~/DPDK/usertools # ./dpdk-setup.py 注意,setup脚本需要在root权限下运行,并且每次重启电脑,都需要重新插入模块和绑定网卡. ...
- keil C 51 strlen库函数使用
在keil c51 程序中,若定义数组 volatile unsigned char data[3]={'G','G','G'};使用strlen(&data);得到的长度是不对的,若定义v ...
- loadrunner汉化【运行时设置】菜单选项截图
来自为知笔记(Wiz)
- oracle 取俩个字符串的差集
思路: --funcation RemoveSameStr(in_str,splitStr) ;用于去除重复值 ; SELECT b.memberid, RemoveSameStr(wm_concat ...
- SpringBoot(八)_springboot集成swagger2
swagger是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试. (1) 引入依赖,我们选择现在最新的版本 <dependency> &l ...
- 如何调换antd中Modal对话框确认按钮和取消按钮两个按钮的位置
今天有个工作是把所有的确认按钮放在取消按钮的左边,类似于下图这样的,公司用的时antd组件 但是antd组件的按钮时确认键放在右边的 可以采用下面的方式,将按钮调换过来: 对的,就是在modal里面的 ...
- JavaWeb基础【1】—— Tomcat
此笔记是学习黑马程序员JavaWeb系列视频的课堂笔记. 感谢黑马程序员. 一.Tomcat概述 Tomcat服务器由Apache提供,开源免费.由于Sun和其他公司参与到了Tomcat的开发中,所以 ...
- Huge Mods UVA - 10692(指数循环节)
题意: 输入正整数a1,a2,a3..an和模m,求a1^a2^...^an mod m 解析: #include <iostream> #include <cstdio> # ...