-
2019-03-13 19:09:51
一、问题
最近遇到了一个比较棘手的问题:我有一个可编辑列表,有操作员-经理-总经理三级审批;但是只有是操作员才可以添加修改,然后发起流程,其他的角色将不能添加修改,对于该可编辑列表只能查看,后面的角色,只能新增审批意见;如何根据登陆用户的角色,来控制页面上可编辑表格的修改权限?
二、分析
角色,权限信息我都可以获取到,目前的问题是,如何修改EasyUI中可编辑表格的【是否可编辑状态】;
该目标实现的难点在于:
1.非全页面设置可读可写,而是局部控制可读可写;
2.要根据角色变化【可编辑表格】的属性;三、解决
基本语法:
在table标签上加入如下信息:
dataOptions="onClickRow:fun1";
dataOptions是添加在【标签】上的属性,里面可以添加用户执行的动作;onClickRow表示用户单击某一行的记录时触发;冒号后面是触发的方法;触发方法如下:
在js中加入如下事件方法:
function fun1(rowIndex,rowData){ //此处添加过滤条件 //下面这句是:是否失效 ${'目标表的id'}.datagrid('getEditor',{index:rowIndex,field:'目标字段'}).target.renderDisabled(true); }
说明:
1.入参rowIndex表示选中的那一行的下表,从0开始;rowData表示那一行的数据;
2.${‘目标表的id’}是用来获取目标表格的所有数据;
3.datagrid表示EasyUI获取表格数据(网格数据)的方法;index,表示下标;field表示那一行的具体的字段;target表示获取目标。renderDisable()方法是渲染方法,表示是否有效;boolean值true表示有效,可以编辑;false表示无效,点击后,会变成灰色的不可编辑的矩形方块;更多相关内容 -
HTML5实现一个可编辑的模板页面
2017-12-27 09:57:46需求:公司在给学校做项目,有一个页面要展示一些考号,座号之类的东西,因为要经常修改,所以在后台要做一个能够自定义的页面,效果如下 创建的组件分为两种:文本组件(自定义要显示的文本,如标题等),数据组件...需求:公司在给学校做项目,有一个页面要展示一些考号,座号之类的东西,因为要经常修改,所以在后台要做一个能够自定义的页面,效果如下
创建的组件分为两种:文本组件(自定义要显示的文本,如标题等),数据组件(如座位号等,只能修改宽高等,内容不可直接编辑)。
首先说明编辑功能的基本实现
1:布局
在每个创建出的组件中,绿色的div(.container)是最外层的div,蓝色的span是用来编辑文本的,上面的工具条也在container中,使其向上偏移显示在外面。顶部的红色长条div(.move)是隐藏起来的,将拖动事件添加到它上面。右下角有一个正方形的div(.zoom),将缩放事件添加到它上面。
2:编辑功能
一般编辑文本使用的是input,但这里用input显然不行,给上图中蓝色的span(也可以是div)添加上contenteditable="true"属性,就可以对其内容进行编辑了。
3:拖动
由于所有的dom都在container中,所以拖动时只需要改变container的位置即可。
$container.find('.move').on('mousedown', function(e) { var $element = $(this).parent(); disX = e.pageX - $element.offset().left; disY = e.pageY - $element.offset().top; $(document).on('mousemove', function(e) { var x = e.pageX - disX; var y = e.pageY - disY; $element.css('left', x); $element.css('top', y); //限制拖动范围 if(x<=0){ $element.css('left', 0); } if(y<=35){ $element.css('top', 35); } //组件靠近顶部时,工具条显示在下方 if(y<=70){ $element.find('.editBox').removeClass('editBoxTop').addClass('editBoxBot'); }else{ $element.find('.editBox').removeClass('editBoxBot').addClass('editBoxTop'); } return false; //防止鼠标移动时选中文字 }) $(document).on('mouseup', function() { $(this).off('mousemove'); }) })
在基本的拖动上加上范围限制,防止组件被拖出页面,同时在组件靠近顶部时,让工具条显示在下方。
4:缩放
$container.find('.zoom').on('mousedown', function(e) { cancelBubble(e); var $element = $(this).parent(); $(document).on('mousemove', function(e) { var x = e.pageX - $element.offset().left; //pagex和offset获取的都是相对document左上角的位置 var y = e.pageY - $element.offset().top; $element.css('width', x); $element.css('height', y); return false; //防止鼠标移动时选中文字 }) $(document).on('mouseup', function() { $(this).off('mousemove'); }) })
这段实现的是缩放的基本功能,后面还要限制他的最小宽高。cancelBubble是取消冒泡的函数
//取消冒泡函数 function cancelBubble(e) { document.all ? (e.cancelBubble = true) : (e.stopPropagation()); }
5:工具条工具条里的功能基本就是对文本进行操作的,在相应的按钮上添加上功能就行了,这里的颜色选择器我使用的一个叫jscolor的插件,在博客里也有些。
6:源码
额,其他地方都是一些DOM和样式的操作,就不在这里一一列举了,放出源码吧,里面有注释(有点乱抱歉= =!),有兴趣的可以看看,有问题可以留言。
CSDN:http://download.csdn.net/download/huangxin112/10175982
CSDN上传时积分最低只能选2分,不能免费,在百度云又传了一份
https://pan.baidu.com/s/1c1Fxa5i
-
C# dataGridView限制某一行的单元格只输入数字的方法之一
2017-06-16 10:23:43dataGridView限制某一行的单元格只输入数字的方法之一 首先,参考了如下的文章: 点击打开链接 然后,给你的dataGridView1添加dataGridView1_EditingControlShowing事件,并在事件的上方定义如下变量: ...Part1. dataGridView限制某一行的单元格只输入数字的方法之一
首先,参考了如下的文章:
然后,给你的dataGridView1添加dataGridView1_EditingControlShowing事件,并在事件的上方定义如下变量:
public DataGridViewTextBoxEditingControl CellEdit = null; // dataGridView1_EditingControlShowing事件的完整代码如下,我是限制第一行和第二行的单元格里只能输入数字: private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { for (int i = 1; i < dataGridView1.Columns.Count; i++) { //如果是第1行和第二行,就限制只能输入数字,第三行不受限制 if ((dataGridView1.CurrentCell.RowIndex == 0) || (dataGridView1.CurrentCell.RowIndex == 1)) { if (this.dataGridView1.CurrentCellAddress.X == i) { { if (this.dataGridView1.CurrentCellAddress.X == i) { CellEdit = (DataGridViewTextBoxEditingControl)e.Control; CellEdit.SelectAll(); CellEdit.KeyPress += Cells_KeyPress; //绑定事件 } } } } else //不然,移除这个事件。。。 { CellEdit = (DataGridViewTextBoxEditingControl)e.Control; CellEdit.SelectAll(); CellEdit.KeyPress -= Cells_KeyPress; //绑定事件 } } } private void Cells_KeyPress(object sender, KeyPressEventArgs e) //自定义事件 { if (!(char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8) e.Handled = true; //if (!(e.KeyChar >= '0' && e.KeyChar <= '9')) e.Handled = true; //if (e.KeyChar == '\b') e.Handled = false; }
特别注意的是,如果不把事件订阅移除,则每个单元格它都检查,不管是不是你选择的行。。。
Part2.dataGridView的其它使用总结
//不允许用户添加行 dataGridView1.AllowUserToAddRows = false; //不显示列标题。。则dataGridView1最左边的那一列不会出现 dataGridView1.ColumnHeadersVisible = false; //更改列标题颜色。。 dataGridView1.EnableHeadersVisualStyles = false; dataGridView1.ColumnHeadersDefaultCellStyle.BackColor = Color.DarkGray; //清空列表 dataGridView1.Rows.Clear(); //如果允许用户动态添加行,则以下语句意思是再添加28行,所以一共是29行。。。 //否则的话,则是总共添加28行 dataGridView1.Rows.Add(28); //把dataGridView1高度设为均等, int h = dataGridView1.Height; for (int i = 0; i < dataGridView1.Rows.Count; i++) { dataGridView1.Rows[i].Height = Convert.ToInt16(h / 32); } //如果发现还是跟页面不符,可以在高度后面修改数值,像这样: dataGridView1.Rows[i].Height = Convert.ToInt16(h / 31) + 3; //第i行第j列元素的访问方式..下标都是从0开始 dataGridView1.Rows[i].Cells[j].Value = "8:30-9:30"; //修改第12行的第0列、1列、2列的背景色为深灰色。。。 dataGridView1[0, 12].Style.BackColor = Color.DarkGray; dataGridView1[1, 12].Style.BackColor = Color.DarkGray; dataGridView1[2, 12].Style.BackColor = Color.DarkGray; //设置dataGridView1的行字体大小 dataGridView1.RowsDefaultCellStyle.Font = new Font("宋体", 12, FontStyle.Regular); //设置dataGridView1的列宽度根据单元格的内容自适应 for (int i = 0; i < dataGridView1.ColumnCount; i++) { dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; }
-
每日一面 - mysql中,innodb表里,某一条数据删除了之后,这条数据会被真实的擦掉吗,还是删除了关系?
2021-01-08 08:42:17但是数据没有被清空,在新一行数据大小小于这一行的时候,可能会占用这一行。这样其实就是存储碎片,要想减少存储碎片,可以通过重建表来实现(例如对于高并发大数据量表,除了归档,还可以通过利用无锁算法Alter...以 Compact 行格式为例:
总结
删除一条记录,数据原有的被废弃,记录头发生变化,主要是打上了删除标记。也就是原有的数据 deleted_flag 变成 1,代表数据被删除。但是数据没有被清空,在新一行数据大小小于这一行的时候,可能会占用这一行。这样其实就是存储碎片,要想减少存储碎片,可以通过重建表来实现(例如对于高并发大数据量表,除了归档,还可以通过利用无锁算法
Alter
修改字段来重建表增加表性能)。Compact 行格式存储
我们来创建一个包含几乎所有基本数据类型的表,其他的例如 geometry,timestamp 等等,也是基于 double 还有 bigint 而来的, text、json、blob等类型,一般不与行数据一起存储,我们之后再说:
create table record_test_1 ( id bigint, score double, name char(4), content varchar(8), extra varchar(16) )row_format=compact;
插入如下几条记录:
INSERT INTO `record_test_1`(`id`, `score`, `name`, `content`, `extra`) VALUES (1, 78.5, 'hash', 'wodetian', 'nidetiantadetian'); INSERT INTO `record_test_1`(`id`, `score`, `name`, `content`, `extra`) VALUES (65536, 17983.9812, 'zhx', 'shin', 'nosuke'); INSERT INTO `record_test_1`(`id`, `score`, `name`, `content`, `extra`) VALUES (NULL, -669.996, 'aa', NULL, NULL); INSERT INTO `record_test_1`(`id`, `score`, `name`, `content`, `extra`) VALUES (2048, NULL, NULL, 'c', 'jun');
目前表结构:
+-------+------------+------+----------+------------------+ | id | score | name | content | extra | +-------+------------+------+----------+------------------+ | 1 | 78.5 | hash | wodetian | nidetiantadetian | | 65536 | 17983.9812 | zhx | shin | nosuke | | NULL | -669.996 | aa | NULL | NULL | | 2048 | NULL | NULL | c | jun | +-------+------------+------+----------+------------------+
查看底层存储文件:
record_test_1.ibd
,用16进制编辑器打开,我这里使用的是Notepad++
和他的HEX-Editor
插件。可以找到如下的数据域(可能会有其中 mysql 生成的行数据不一样,但是我们创建的行数据内容应该是一样的,而且数据长度应该是一摸一样的,可以搜索其中的字符找到这些数据):我们这里先直接给出这些数据代表的意义,让大家直观感受下:
变长字段长度列表:10 08 Null值列表:00 记录头信息:00 00 10 00 47 隐藏列DB_ROW_ID:00 00 00 00 08 0c 隐藏列DB_TRX_ID:00 00 00 03 c9 4d 隐藏列DB_ROLL_PTR:b9 00 00 01 2d 01 10 列数据id(1):80 00 00 00 00 00 00 01 列数据score(78.5):00 00 00 00 00 a0 53 40 列数据name(hash):68 61 73 68 列数据content(wodetian):77 6f 64 65 74 69 61 6e 列数据extra(nidetiantadetian):6e 69 64 65 74 69 61 6e 74 61 64 65 74 69 61 6e 变长字段长度列表:06 04 Null值列表:00 记录头信息:00 00 18 00 37 隐藏列DB_ROW_ID:00 00 00 00 08 0d 隐藏列DB_TRX_ID:00 00 00 03 c9 4e 隐藏列DB_ROLL_PTR:ba 00 00 01 2f 01 10 列数据id(65536):80 00 00 00 00 01 00 00 列数据score(17983.9812):b5 15 fb cb fe 8f d1 40 列数据name(zhx):7a 68 78 20 列数据content(shin):73 68 69 6e 列数据extra(nosuke):6e 6f 73 75 6b 65 Null值列表:19 记录头信息:00 00 00 00 27 隐藏列DB_ROW_ID:00 00 00 00 08 0e 隐藏列DB_TRX_ID:00 00 00 03 c9 51 隐藏列DB_ROLL_PTR:bc 00 00 01 33 01 10 列数据score(-669.996):87 16 d9 ce f7 ef 84 c0 列数据name(aa):61 61 20 20 变长字段长度列表:03 01 Null值列表:06 记录头信息:00 00 28 ff 4b 隐藏列DB_ROW_ID:00 00 00 00 08 0f 隐藏列DB_TRX_ID:00 00 00 03 c9 54 隐藏列DB_ROLL_PTR:be 00 00 01 3d 01 10 列数据id(2048):80 00 00 00 00 00 08 00 列数据content(c):63 列数据extra(jun):6a 75 6e
可以看出,在 Compact 行记录格式下,一条 InnoDB 记录,其结构如下图所示:
Compact 行格式存储 - 变长字段长度列表
对于像 varchar, varbinary,text,blob,json以及他们的各种类型的可变长度字段,需要将他们到底占用多少字节存储起来,这样就省去了列数据之间的边界定义,MySQL 就可以分清楚哪些数据属于这一列,那些不属于。Compact行格式存储,开头就是变长字段长度列表,这个列表包括数据不为NULL的每个可变长度字段的长度,并按照列的顺序逆序排列。
例如上面的第一条数据:
+-------+------------+------+----------+------------------+ | id | score | name | content | extra | +-------+------------+------+----------+------------------+ | 1 | 78.5 | hash | wodetian | nidetiantadetian | +-------+------------+------+----------+------------------+
有两个数据不为NULL的字段
content
和extra
,长度分别是 8 和 16,转换为 16 进制分别是:0x08,0x10。倒序的顺序排列就是10 08
这是对于长度比较短的情况,用一字节表示长度即可。如果变长列的内容占用的字节数比较多,可能就需要用2个字节来表示。那么什么时候用一个字节,什么时候用两个字节呢?
我们给这张表加一列来测试下:
alter table `record_test_1` add column `large_content` varchar(1024) null after `extra`;
这时候行数据部分并没有变化。
- 如果 字符集的最大字节长度(我们这里字符集是latin,所以长度就是1)乘以 字段最大字符个数(就是varchar里面的参数,我们这里的
large_content
就是1024) < 255,那么就用一个字节表示。这里对于large_content
,已经超过了255. - 如果超过255,那么:
- 如果 字段真正占用字节数 < 128,就用一个字节
- 如果 字段真正占用字节数 >= 128,就用两个字节
问题一:那么为什么用 128 作为分界线呢?
一个字节可以最多表示255,但是 MySQL 设计长度表示时,为了区分是否是一个字节表示长度,规定,如果最高位为1,那么就是两个字节表示长度,否则就是一个字节。例如,01111111,这个就代表长度为 127,而如果长度是 128,就需要两个字节,就是 10000000 10000000,首个字节的最高位为1,那么这就是两个字节表示长度的开头,第二个字节可以用所有位表示长度,并且需要注意的是,MySQL采取 Little Endian 的计数方式,低位在前,高位在后,所以 129 就是 10000001 10000000。同时,这种标识方式,最大长度就是 2^15 - 1 = 32767,也就是32 KB。问题二:如果两个字节也不够表示的长度,该怎么办?
innoDB 页大小默认为 16KB,对于一些占用字节数非常多的字段,比方说某个字段长度大于了16KB,那么如果该记录在单个页面中无法存储时,InnoDB会把一部分数据存放到所谓的溢出页中,在变长字段长度列表处只存储留在本页面中的长度,所以使用两个字节也可以存放下来。这个溢出页机制,我们后面和Text字段一起再说。然后对第一行数据填充
large_content
字段,对于第二行,将新字段更新为空字符串。update `record_test_1` set `large_content` = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' where id = 1; update `record_test_1` set `large_content` = '' where id = 1;
查看数据:
发现
COMPACT
行记录格式下,对于变长字段的更新,会使原有数据失效,产生一条新的数据在末尾。第一行数据原有的被废弃,记录头发生变化,主要是打上了删除标记,这个稍后我们就会提到。第一行新数据:
变长字段长度列表:82 80 10 08 Null值列表:00 记录头信息:00 00 30 01 04 隐藏列DB_ROW_ID:00 00 00 00 08 0c 隐藏列DB_TRX_ID:00 00 00 03 c9 6e 隐藏列DB_ROLL_PTR:4f 00 00 01 89 1c 51 列数据id(1):80 00 00 00 00 00 00 01 列数据score(78.5):00 00 00 00 00 a0 53 40 列数据name(hash):68 61 73 68 列数据content(wodetian):77 6f 64 65 74 69 61 6e 列数据extra(nidetiantadetian):6e 69 64 65 74 69 61 6e 74 61 64 65 74 69 61 6e 列数据large_content(abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz):61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a
可以看到,变长字段长度列表变成了
82 80 10 08
,这里的large_content
字符编码最大字节大小为1,字段字符最大个数为1024,这里第一行记录这个字段字符数量是130,所以应该用两个字节。130*1转换成16进制为 0x82 也就是 0x02 + 0x80,最高位标识1之后,就是 0x82 + 0x80,对应咱们的变长字段长度列表的开头。而新的第二行,变长字段长度列表变成了
00 06 04
,因为实际large_content
占用了0个字节。Compact 行格式存储 - NULL 值列表
某些字段可能可以为 NULL,如果对于 NULL 还单独存储,是一种浪费空间的行为,和 Compact 行格式存储的理念相悖。采用 BitMap 的思想,标记这些字段,可以节省空间。Null值列表就是这样的一个 BitMap。
NULL 值列表仅仅针对可以为 NULL 的字段,如果一个字段标记了
not null
,那么这个字段不会进入这个 NUll 值列表的 BitMap 中。NULL值列表占用几个字节呢?每个不为 NULL 的字段,占用一位,每超过八个字段,就是 8 位,就多一个字节,不足一个字节,高位补0。假如一个表所有字段都是
not null
,那么就没有NULL 值列表,也就占用 0 个字节。并且,每个字段在这个 bitmap 中,类似于变长字段长度列表,是逆序排列的。+-------+------------+------+----------+------------------+------------------------------------------------------------------------------------------------------------------------------------+ | id | score | name | content | extra | large_content | +-------+------------+------+----------+------------------+------------------------------------------------------------------------------------------------------------------------------------+ | 1 | 78.5 | hash | wodetian | nidetiantadetian | abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz | | 65536 | 17983.9812 | zhx | shin | nosuke | lex | | NULL | -669.996 | aa | NULL | NULL | NULL | | 2048 | NULL | NULL | c | jun | NULL | +-------+------------+------+----------+------------------+------------------------------------------------------------------------------------------------------------------------------------+
针对第一第二行记录,由于没有为 NULL 的字段,所以他们的 NULL 值列表为00.
针对第三行记录,他的 NULL 字段分别是id
,content
,extra
,large_content
,分别是第一,第四,第五,第六列,那么 NULL 值列表为:00111001,也就是 0x39。在加入新字段之前NULL 字段分别是id
,content
,extra
,分别是第一,第四,第五列,那么 NULL 值列表为:00011001,也就是 0x19
针对第四行记录,他的 NULL 字段分别是score
,name
,large_content
,分别是第二,第三,第六列,那么 NULL 值列表为:00100110,也就是 0x26。在加入新字段之前NULL 字段分别是score
,name
,分别是第二,第三列,那么 NULL 值列表为:00000110,也就是 0x06。Compact 行格式存储 - 记录头信息
对于Compact 行格式存储,记录头固定为5字节大小:
名称 大小(bits) 描述 无用位 2 目前没用到 deleted_flag 1 记录是否被删除 min_rec_flag 1 B+树中非叶子节点最小记录标记 n_owned 4 该记录对应槽所拥有记录数量 heap_no 13 该记录在堆中的序号,也可以理解为在堆中的位置信息 record_type 3 记录类型,普通数据记录为000,节点指针类型为001,伪记录首记录 infimum 行为010,伪记录最后一个记录 supremum 行为011,1xx的为保留的 next_record pointer 16 页中下一条记录的相对位置 对于更新前的第一行和第二行:
第一行记录头信息:00 00 10 00 47 转换为2进制:00000000 00000000 00010000 00000000 01000111 无用位:00,deleted_flag:0,min_rec_flag:0,n_owned:0000,heap_no:0000000000010,record_type:000,next_record:00000000 01000111 第二行记录头信息:00 00 18 00 37 转换为2进制:00000000 00000000 00011000 00000000 00110111 无用位:00,deleted_flag:0,min_rec_flag:0,n_owned:0000,heap_no:0000000000010,record_type:000,next_record:00000000 01000111
对于更新后的原始第一行和第二行:
第一行记录头信息:20 00 10 00 47 转换为2进制:00010000 00000000 00010000 00000000 01000111 无用位:00,deleted_flag:1,min_rec_flag:0,n_owned:0000,heap_no:0000000000010,record_type:000,next_record:00000000 01000111 第二行记录头信息:20 00 18 00 37 转换为2进制:00010000 00000000 00011000 00000000 00110111 无用位:00,deleted_flag:1,min_rec_flag:0,n_owned:0000,heap_no:0000000000010,record_type:000,next_record:00000000 01000111
可以看出,原有的数据 deleted_flag 变成 1,代表数据被删除。
对于更新后的新的第一行和第二行:
第一行记录头信息:00 00 30 00 ca 转换为2进制:00000000 00000000 00110000 00000000 11001010 无用位:00,deleted_flag:0,min_rec_flag:0,n_owned:0000,heap_no:0000000000011,record_type:000,next_record:00000000 11001010 第二行记录头信息:00 00 38 fe e6 转换为2进制:00000000 00000000 00111000 11111110 11100110 无用位:00,deleted_flag:0,min_rec_flag:0,n_owned:0000,heap_no:0000000000111,record_type:000,next_record:11111110 11100110
这些信息的其他字段,在我们之后用到的时候,会详细说明。
Compact 行格式存储 - 隐藏列
隐藏列包含三个:
列名 大小(字节) 描述 DB_ROW_ID 6 主键ID,这个列不一定会生成。优先使用用户自定义主键作为主键,如果用户没有定义主键,则选取一个 Unique 键作为主键,如果表中连 Unique 键都没有定义的话,则会为表默认添加一个名为 DB_ROW_ID 的隐藏列作为主键 DB_TRX_ID 6 产生当前记录项的事务id,每开始一个新的事务时,系统版本号会自动递增,而事务开始时刻的系统版本号会作为事务id,事务 commit 的话,就会更新这里的 DB_TRX_ID DB_ROLL_PTR 7 undo log 指针,指向当前记录项的 undo log,找之前版本的数据需通过此指针。如果事务回滚的话,则从 undo Log 中把原始值读取出来再放到记录中去 这里我们先不详细展开这些列的说明,只是先知道这些列即可,只会会在聚簇索引说明以及多版本控制分析的章节中详细说明。
Compact 行格式存储 - 数据列 bigint 存储
对于 bigint 类型,如果不为 NULL,则占用8字节,首位为符号位,剩余位存储数字,数字范围是 -2^63 ~ 2^63 - 1 = -9223372036854775808 ~ 9223372036854775807。如果为 NULL,则不占用任何存储空间。
存储时,如果为正数,则首位 bit 为1,如果为负数,则首位为 0 并用补码的形式存储。
对于我们的四行数据:
第一行列数据id(1):80 00 00 00 00 00 00 01 第二行列数据id(65536):80 00 00 00 00 01 00 00 第三行行列数据id(NULL):空 第四行列数据id(2048):80 00 00 00 00 00 08 00
其他的类似的整数存储,tinyint(1字节),smallint(2字节),mediumint(3字节),int(4字节)等,只是字节长度上面有区别。对应的无符号类型,tinyint unsigned,smallint unsigned, mediumint unsigned,int unsigned,bigint unsigned等等,仅仅是是否有符号位的区别。
同时,这里提一下
bigint(20)
里面这个 20 的作用。他只是限制显示,和底层存储没有任何关系。整型字段有个 zerofill 属性,设置后(例如bigint(20) zerofill
),在数字长度不够 20 的数据前面填充0,以达到设定的长度。这个 20 就是显示长度的设定。Compact 行格式存储 - 数据列 double 存储
double 的存储对于非 NULL 的列,符合 IEEE 754 floating-point “double format” bit layout 这个统一标准:
- 最高位 bit 表示符号位(0x8000000000000000)
- 第二到第十二的 bit 表示指数(0x7ff0000000000000)
- 剩下的 bit 表示浮点数真正的数字(0x000fffffffffffffL)
同时,Innodb存储在数据文件上的格式为 Little Edian,需要进行反转后,才能取得字段的真实值。
同样的,如果为 NULL, 则不占用空间。例如:
第一行列数据score(78.5):00 00 00 00 00 a0 53 40 翻转: 40 53 a0 00 00 00 00 00 二进制: 01000000 01010011 10100000 00000000 00000000 00000000 00000000 00000000 符号位:0,指数位10000000101 = 1029,减去阶数 1023 = 实际指数 6,小数部分0.0011101000000000000000000000000000000000000000000000,转换为十进制为0.125 + 0.0625 + 0.03125 + 0.0078125 = 0.2265625, 加上隐含数字 1 为 1.2265625, 之后乘以 2 的 6 次方就是 1.2265625 * 64 = 78.5
计算过程较为复杂,可以利用 Java 的
Double.longBitsToDouble()
转换:public static void main(String[] args) { System.out.println(Double.longBitsToDouble(0x4053a00000000000L)); }
输出为
78.5
类似的类型,float,也是相同的格式,只是长度减半。
Compact 行格式存储 - 数据列 char 存储
对于定长字段,不需要存长度信息直接存储数据即可,如果不足设定的长度则补充。对于char类型,补充 0x20, 对应的就是空格。
例如:
第一行列数据name(hash):68 61 73 68 第二行列数据name(zhx):7a 68 78 20 第三行列数据name(aa):61 61 20 20 第四行列数据name(NULL):空
对于类似的 binary 类型,补充 0x00。
Compact 行格式存储 - 数据列 varchar 存储
因为数据开头有可变长度字段长度列表,所以 varchar 只需要保存实际的数据即可,不需要填充额外的数据。
正是由于这个特性,对于可变长度字段的更新,一般都是将老记录标记为删除,在记录末尾添加新的一条记录填充更新后的记录。这样提高了更新速度,但是增加了存储碎片。
每日一刷,轻松提升技术,斩获各种offer:
- 如果 字符集的最大字节长度(我们这里字符集是latin,所以长度就是1)乘以 字段最大字符个数(就是varchar里面的参数,我们这里的
-
Nginx限制IP访问某些页面
2018-08-20 18:19:08首先要建一个封ip的配置文件blockips.conf,然后vi blockips.conf编辑此文件,在文件中输入要封的ip。 deny 1.2.3.4; deny 91.212.45.0/24; deny 91.212.65.0/24; 然后保存此文件,并且打开nginx.conf文件,在... -
怎样将微信页面模板添加到公众号自定义菜单里?
2020-03-26 23:59:16经常有小伙伴问我怎样将多篇文章放到我们公众号的自定义菜单里面,这里就涉及到一个知识点,叫做微信页面模板。 微信页面模板可以帮助用户将数万篇的图文或者是视频整理成一个链接进行分发,不仅让我们操作起来更加... -
一种在openwrt路由器突破校园网web认证设备限制的方法(对swu校园网的一次实践)
2019-05-06 17:20:36摘要:本文主要是针对通过路由器wan口连接校园... 前言 维基百科openwrt介绍: OpenWrt是适合于嵌入式设备的一个Linux发行版。...相对原厂固件而言,OpenWrt不是一个单一、静态的固件,而是提供了一个可添加软件包... -
微信小程序富文本编辑器的纯原生实现(一)
2018-10-27 03:48:05先上图 主要实现以下功能: 1. 富文本编辑,图文混排 2. 图片添加原则上可以无限,demo做了限制,最多四张 3. 删除图片,图片上下文字合并 原理和机制,以及demo稍后跟上 ... -
django博客开发:添加富文本编辑器ckeditor
2018-04-06 18:03:00Markdown用的不太习惯,于是决定添加一个富文本编辑器。ckeditor是一个老牌的编辑器,GitHub上有一个第三方模块django-ckeditor封装了所有功能,把import到我们的项目里,然后设置一下参数,就可轻松使用了。github... -
ArcGIS Pro 简明教程(3)数据编辑
2016-10-10 09:54:38数据编辑是GIS中最常用的功能之一,ArcGIS Pro在GIS数据编辑上使用习惯有一定的改变,因此,本章可以重点看看一些编辑工具的使用和使用技巧。 创建数据 GIS数据编辑经常需要创建新的geodatabase或者featureclass... -
elementUI表格实现可编辑和增加行功能--直接复制即可
2020-07-16 17:24:37= "操作") {//哪些字段不可编辑,可以在if里面做限制,可编辑的字段往下执行 event.target.innerHTML = ""; //双击添加一个input框 let cellInput = document.createElement("input"); cellInput.value = ""; //设置... -
SourceInsight 4.0 之四 项目配置(库文件引入、配置宏添加、快捷键修改等)
2019-06-28 13:51:23如果不添加,Source Insight 将找不到一些库函数的定义,例如:memcpy 函数 添加自己代码中使用的各种宏值。这一点是由于,在实际开发中,我们经常有一些全局的宏,如下图: 或者说有一些编译器自己定义的宏值,... -
嵌入式 -固件防复制系列【1】GD32代码读保护
2022-02-27 19:05:59GD32 flash读保护开启及现象分析 -
福昕高级pdf编辑器10企业版 v10.1.0中文直装版
2020-12-22 14:07:38另外,用户使用它能够直接对PDF文档进行创建、修改、转换操作,并且还能够将PDF文档直接转化为Word等格式文件,这样一来,用户可以轻松的对文档文件进行管理编辑、保护或者共享,更好的提高用户的工作效率。... -
Adobe Acrobat pro给pdf文件添加水印和加密编辑功能
2017-02-07 14:51:36软件:Adobe Acrobat pro 10.1.0版本一、pdf添加水印 1.打开软件找到工具选项--水印点击添加如下图所示: 2.打开水印添加页面添加要写的文字调整字号和角度,注意多个文件的话可以使用右下角标记的多 个文档来进行... -
Django_实现编辑和删除功能
2020-07-24 15:34:58一、效果图 点击编辑图标,弹窗显示编辑页面。自动回填内容 二、前端显示“编辑”入口 # 在table的<thead>里加入 <th>编辑</th> # 在table的<tbody>里加入 <td><a style="color:... -
如何给PDF加密码保护?这3种方法总有一个能用上
2020-08-17 17:16:02平时我们修改PDF文件都要用到PDF编辑器,那么首先就来说一说编辑器的加密操作方法。用极速PDF编辑器打开需要添加密码保护的PDF文档后,直接点击工具栏“安全保护”打开加密功能进入设置: 打开“文档安全性”设置... -
为百度文本编辑器UEditor添加附件管理功能
2016-11-02 22:59:22最近朋友的一个项目需要一个文本编辑器,让我突然想起那个百度编辑器UEditor,功能比较齐全而且开源,但也有很多bug和不足。 http://ueditor.baidu.com/website/onlinedemo.html 一年前我就曾经关注过,让我... -
Win10设置本地用户限制使用指定程序与文件资源
2018-10-10 11:44:41前言 针对特定win10用户登录解决只能访问指定程序和文件,从而保证个人隐私的解决方案。...3.在中间的用户列表上,右键刚刚创建的用户–》点“属性”–》隶属于–》点底下的添加–》输入框输入组名称“Guests”后... -
navicat中怎么添加约束
2021-01-20 02:15:48打开navicat工具连接上mysql服务,然后选择打开一个数据库,这里为了演示选择一个测试数据库,然后为用户表和学校表的外键。...在设计表页面,默认是字段...在弹出的栏位下拉列表中,选择一个要添加外键的字段,这里是... -
9种免费在线PDF编辑网站
2019-07-01 13:14:25在线PDF编辑网站LightPDFLightPDF主要特点:SmallPDFSmallPDF主要特点:iLovePDF主要特点:PDFdo主要的特点:迅捷 PDF 转换器主要特点:依奇在线超级转换工具主要特点:CleverPDF主要特点:转转大师主要特点:设定... -
华为C语言编程规范(精华总结)
2020-03-24 09:48:5511、禁止在 extern "C" 中包含头文件 在extern "C"中包含头文件,会导致extern "C"嵌套,Visual Studio对extern "C"嵌套层次有限制,嵌套层次太多会编译错误。 在extern "C"中包含头文件,可能会导致被包含头文件的... -
netprofm属性安全是灰色无法编辑
2020-06-05 10:05:31在第一个常规页签,找到它的应用ID.复制, 打开注册表 按如下操作: 打开 HKEY_CLASSES_ROOT\AppID\按F3查找,输入刚才复制的ID 右键在找到的项目上单击 选择权限 高级 所有者-修改为管理员 点击应用 -确定 选中... -
(微信编辑器)UEditor富文本嵌入135编辑器
2019-06-08 15:44:53UEditor简介 UEditor是由百度「FEX前端研发团队」开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于...135编辑器是一款提供微信公众号文章排版和内容编辑的在线工具,样式丰富,支持... -
常用功能-添加、修改功能测试点
2018-08-28 15:21:14添加功能 1.特殊键:(1)是否支持Tab键 (2)是否支持回车键 2.提示信息:不符合要求的地方是否有错误提示 3.唯一性:字段唯一的,...(1)对编辑页的每个编辑项进行修改,点击保存,是否可以保存成功,检查想... -
gitlab配置自带Nginx实现网段访问限制、gitlab配置访问黑白名单、gitlab访问IP限制
2019-03-19 14:44:00一、在实际应用中,我们个人搭建gitlab环境的时候,都是在公司内网的情况下,只为单独的某个企业/公司使用,所以此时会出现某些特殊的访问需求,比如我只允许公司某个网段中的IP地址访问,或者只允许某几台主机访问... -
常见编辑器漏洞
2019-03-26 21:38:46FCKeditor编辑器页/查看编辑器版本/查看文件上传路径 FCKeditor编辑器页 FCKeditor/_samples/default.html 查看编辑器版本 FCKeditor/_whatsnew.html 查看文件上传路径 fckeditor/edit... -
SpringBoot(30) 整合PageOffice实现在线编辑Word和Excel
2020-07-15 17:07:47一、前言 二、 三、 注册成功后,正常打开Word文件,之后就可以进行自己的神操作了… -
mysql5.7性能提升一百倍调优宝典
2020-05-06 10:07:36每一个参数干吗? 在某些典型硬件配置下的db上参数该设多少? 设会怎么样? 不设会怎么样? 有什么坑如何填坑? 有些参数怎么算、算法又如何 这种style来写的,具体请看文档! 一千个DBA就有一千种配置方式! ... -
百度移动营销页常见问题汇总,99%的人不知道
2018-06-30 10:40:095,798 view s 所属分类:信息流营销 ...目前服务号支持的问题为:入口、高级编辑器、审核、添加链接、线索数据、商桥、离线宝、页面操作报错、电话填写、文字字数限制、固定头部填写、操作异常...