ODA性能概述

前一段时间对ODA进行了大概一周的测试,简单描述一下性能相关的测试结果。
Oracle的一体机是将软件和硬件结合在一起打包进行出售,那么硬件如何配置势必做过大量的测试之后才确定下来,ODA显然也是精心调测后给出的配置方案。
首先看一下ODA的硬件配置:
包含两个等同配置的节点:
2CPU,6核处理器,每个节点12核处理器;
每个节点96G内存;
每个节点配置2块500G 7200转的SATA硬盘,用来存放操作系统和数据库软件;
共享磁盘部分:
总共20块600G 15000转的SAS硬盘,底层不进行RAID,完全由ASM实现3重镜像,冗余后可用容量4T;
4块73G SAS SSD固态硬盘,用来存储REDO,同样使用ASM实现3重镜像;
网络部分:
提供了两个节点间内部通信的1G网络连接;
对外提供服务的1G网络连接端口;
对外提供服务的10G网络连接端口。
无论是CPU、内存、磁盘数量和容量还是网络连接数量都是配置平衡的,这使得ODA在处理绝大部分工作时都不会碰到明显的性能瓶颈。
经过测试,ODA磁盘的ORION测试结果为:
20块SAS盘只读方式:
SIMPLE方式:
IOPS=5910 MBPS=1604.98
ADVANCE方式:-run advanced -testname oda_big -size_small 8 -size_large 1024 -type rand -simulate concat -write 0 -duration 10 -matrix basic -num_disks 20
IOPS=5056 MBPS=1421.27
读写混合:
ADVANCE方式:-run advanced -size_small 8 -size_large 1024 -type rand -testname write_hdd -simulate concat -write 100 -duration 10 -matrix basic -num_disks 20
IOPS=4484 MBPS=1451.27
4块SSD只读方式:
SIMPLE方式:IOPS=59210 MBPS=1032.02
读写混乱方式:
ADVANCE方式:-run advanced -size_small 8 -size_large 1024 -type rand -testname write_flash -simulate concat -write 100 -duration 10 -matrix basic -num_disks 4
IOPS=46902 MBPS=543.66
可以看到,ORION测试的性能来看,ODA的表现还是不错的。
测试了一个真实的案例,SQLLDR加载大约20M的80W条记录在普通的台式机上耗时3分14秒49,而在ODA上运行同样的SQLLDR命令,仅需15秒30。几乎是台式机13分之一。
之后跑了一个单线程的SQL语句,两个表通过SUBSTR后的条件进行管理,完全的CPU独占型操作,ODA所用时间基本上是台式机的40%左右。
最后通过SWINGBENCH进行压力测试,客户注册10,浏览产品90,订单产品20,处理订单30,浏览订单50,配置并发4500用户的情况下,最大TPS达到了1330是,平均TPS达到637。最大响应延迟为734,平均响应延迟175。
对于ODA面对的客户环境(Oracle官方定义为总数据小于3T)来说,ODA能满足大部分情况下的性能要求。

Posted in ORACLE | Tagged , , , , , , , | Leave a comment

Oracle高可用最佳实践总结

这篇文档主要介绍Oracle高可用技术的适用场景。
如果对于ASM、CLUSTER、RAC和DATA GUARD还不是很了解,没有必要着急看这篇文档,因为文档并不会对这些技术细节进行描述,文档主要介绍每种高可用技术的适用场景,以及如何将多种高可用技术组合起来,从而达到最好的效果。
除了架构上的高可用设计外,文章还描述了各种日常操作的高可用最佳实践,以及部分最佳实践的参数配置等。

Posted in BOOKS | Leave a comment

Oracle DBA手记2总结

这本书是参加ACOUG活动的时候出版社的赠品,一直没有整块的时间细读,不过利用一些零碎的时间也将其读完了,虽然看完这本书的跨度已经超过了一年,不过总的来说印象还是比较深的。
在详细阅读之前,我就提到了,崔华的文章绝对值得仔细研究,阅读之后果然证实了我们观点,其中的一些恢复案例充分展示了他对于Oracle内容数据结构认识之深刻。难怪Eygle不只一次的评价他,没有崔华打不开的数据库。
当然除了崔华问题外,其他人的一些问题也绝对值得一读。Eygle的文章自不必说,而晶晶小妹的回滚段的研究也是非常深入的。此外,野花的CONNECT BY语法研究对于想要提高SQL水平的同学绝对是经典之作,很多看似和树形查询没有关系的例子,却可以利用CONNECT BY来完美解决。
最近一段时间看书的进度有点慢,家里已经放了很多值得一读的书了,看来需要加快进度了。

Posted in BOOKS | Leave a comment

ODA中的ILOM组件

在ODA中,引入了ILOM固件,使得ODA的方便性和可管理性进一步增强。
Oracle ILOM是Oracle Integrated Lights Out Manager的缩写,最早在EXADATA上引入,随着ODA的诞生,这个功能也引入到了ODA上面。
这个组件提供对外的网络访问接口,可以通过图形化的工具实现两个主机的管理。包括开机、部署节点操作系统、设置网络、关机等一系列的命令。这个组件只要主机的电源接电后自动启用,因此开机、安装系统等一系列以往需要现场人员配合的工作可以很方便的远端完成。如果系统异常DOWN机没有启动后,也不再需要现场有人去专门按POWER进行重启了,显然这个功能使得ODA的方便性和易维护性进一步的提升。

Posted in ORACLE | Tagged , , | Leave a comment

ODA的高可用冗余

ODA作为一个一体机,在很多硬件和软件上进行了冗余,避免单点故障对系统的可用性造成影响。
ODA的硬件包括2个Sun Fire X 4370M2,通过RAC或RAC ONE NODE架构实现服务器的冗余;
每个服务器上包含两个冗余热切换的风扇,任何一个风扇异常不会导致系统故障;
服务器包含两组电源,任意一个电源损坏或任意一个电源无法供电都不会对系统造成影响;
每个服务器上集成了10个网络接口,其中两个网络接口用来绑定冗余进行内部连接(PRIVATE IP),两个网络接口绑定用来提供外部客户端访问(PUBLIC IP),两个10G网络接口绑定对外提供网络访问;另外4个接口绑定为两个网络接口提供访问;
两个服务器上按照了20块600G硬盘和4块73G SSD固体硬盘。这两部分磁盘通过ASM的三种镜像进行保护;
共享磁盘和服务器之间存在2个缓冲芯片,每个芯片单独连接到每个服务器上,从而避免单点问题。
可以看到,通过硬件上对所有的组件进行冗余,避免了单点问题;利用RAC和ASM的特性对服务器和磁盘进行保护,从而彻底避免了单点故障对于系统可用性的影响。
对于ODA的硬件和软件冗余进行了简单的测试:
无论是PRIVATE IP和PUBLIC IP都使用两个网卡进行了绑定,手工关闭任意一个网卡,都不会影响RAC环境的正常运行;
将其中一个电源的插头拔下,ODA运行正常;
由于ASM部署了3重镜像,因此通过DD命令将任意两块盘清0,并没有造成数据库的崩溃,只是从ASM中看到,这两块盘的状态异常。通过简单的ASM磁盘组操作,将这两块盘删除并重新添加到磁盘组中,磁盘组的状态恢复正常。在磁盘的选择上,有一块盘是包含VOTING仲裁盘,整个过程ODA正常运行。
简单总结一下,ODA通过硬件和软件实现了冗余和高可用性,避免了任何一个环境上的单点故障,系统可用性很高。

Posted in ORACLE | Tagged , , , , , , | Leave a comment

10.2出现SQL Memory Manager latch类型的latch free

客户环境出现了明显的LATCH FREE等待事件,而等待的latch类型为sql memory manager latch。
详细版本为10.2.0.5 RAC for Hp-ux,问题出现时,AWR的TOP 5信息为:
Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class
latch free 387,948 1,686,005 4,346 60.8 Other
CPU time 219,941 7.9
gc buffer busy 19,927,407 8,938 0 .3 Cluster
gc current block 2-way 6,143,005 5,328 1 .2 Cluster
db file sequential read 789,784 4,744 6 .2 User I/O

在TOP 5中latch free所占DBTIME的比例已经超过了60,显然在这种情况下,数据库无法正常的处理请求,操作系统上CPU处于100%繁忙状态。
查询MOS,发现导致问题的原因在于PGA的设置不足,详见文档Bug 9732503 latch free waits for SQL Memory Manager latch / extra child cursors,虽然当前的PGA命中率并不是很低,达到了96.88%,不过其他方面都与bug描述的非常接近。
这个bug影响的版本包括10.2.0.4、10.2.0.5和11.2.0.1,Oracle在11.2.0.2和11.1.0.7中被FIXED,对于当前10.2的版本,最简单的解决这个问题的方法就是提高PGA_AGGREGATE_TARGET的值。
客户将PGA_AGGREGATE_TARGET从5G调整到10G后,这个问题没有再次出现。

Posted in ORACLE | Tagged , | Leave a comment

20120825 ACOUG活动

7月的ACOUG活动由于不在北京错过了,还好这次的活动赶上了。
发现我和Exadata没有太大缘分,已经两次错过了ACOUG上的Exadata的主题了。不过这个月的演讲同样精彩,由Eygle和崔华两人带来的三个主题。
第一个主题是崔华的优化系列的最终章,主要讨论了优化的方法论。这个分享主题中无论是具体的案例还是对于优化方法论的总结,无不体现出崔华对于SQL优化,对于CBO的深入理解。听了崔华这三次系列的讲座,也使我对于他即将出版的大作的兴趣提到了最高。
第二个主题是Eygle带来一个主题,其实这个主题只包含了一个内容:LOG FILE SYNC,虽然只有一个主题,但是其中包含的细节内容足足讲了一个半小时,能把一个看似简单的等待时间研究到如此透彻的地步,至少国内应该是无出其右的了。
最后仍然是崔华带来的ASM元数据损坏分析,这个案例并没有给出问题的真正解决方案,但是问题的分析、诊断过程给人留下了深刻的印象,而且他对于ASM元数据的理解几乎达到了如指掌的地步,难怪Eygle曾不止一次的提到崔华没有打不开的数据库。

Posted in NEWS | Leave a comment

ODA环境同一服务器中资源划分(二)

简单描述如何实现在同一台服务器上不同的应用之间进行资源划分。
这里介绍资源管理器的方式。
无论是Exadata还是ODA,服务器的配置都越来越强大。因此都存在着把多个应用集中到一起的需求。
对于Exadata而言,一般来说部署的应用数据量大,并发应用高,很少会有多个应用同时部署在一个数据库服务器上的需求,反而经常是需要RAC中的多个节点同时支持某个应用,因此对于Exadata来说,应用资源划分的解决方案是SERVER POOL。
而ODA则和Exadata不同,由于ODA受扩展性,磁盘容量以及配置的限制,因此把多个应用集成到ODA上,那么这些应用多半都是小应用,考虑到ODA只有两个节点组成的RAC,因此对于ODA来说,如何在同一个服务器上给各个应用划分资源,而尽量减少应用之间的相互干扰就是十分有意义的事情了。
除了利用操作系统上的解决方案外,Oracle提供了两种方式的解决方案。一个是通过把多个应用分布到多个数据库中,通过限制每个数据库可以使用的CPU数量实现,即INSTANCE STAGE;另一个是把所有的应用集中到一个数据库,通过数据库的资源管理器实现资源的划分。
如果要使用资源管理器来分配资源,那么需要将所有的应用集中到同一个数据库中,然后根据用户、访问方式以及主机名的不同来设定不同的资源组,并将CPU资源按照一定的比例分配给不同的资源组。
在ODA上使用SWINGBENCH进行压力测试,选择100G的订单环境进行测试,当并发达到6000左右时,ODA两个服务器的CPU基本跑满,前端SWINGBENCH开始出现连接超时的情况,说明当前这种压力已经是服务器所能支持的最大值了。
此时,如果数据库中存在其他的应用,那么这些应用势必会受到压力测试的影响,应用访问的效率必然严重下降。
下面看一个简单的例子,数据库中存在两个用户分布对应两个不同的应用,可以通过下面的方法来给不同的应用分配CPU时间片资源:

SQL> BEGIN
  2          DBMS_RESOURCE_MANAGER.CLEAR_PENDING_AREA();
  3          DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
  4          DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(CONSUMER_GROUP => 'SOE_GROUP',COMMENT => 'soe first group');
  5          DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP(CONSUMER_GROUP => 'S2_GROUP', COMMENT => 'soe2 group');
  6          DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING(ATTRIBUTE => DBMS_RESOURCE_MANAGER.ORACLE_USER, VALUE => 'SOE', CONSUMER_GROUP => 'SOE_GROUP');
  7          DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING(ATTRIBUTE => DBMS_RESOURCE_MANAGER.ORACLE_USER, VALUE => 'SOE2', CONSUMER_GROUP => 'S2_GROUP');
  8          DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
  9          DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
 10  END;
 11  /
PL/SQL PROCEDURE successfully completed.
SQL> BEGIN
  2          DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP(GRANTEE_NAME => 'SOE', CONSUMER_GROUP => 'SOE_GROUP', GRANT_OPTION => FALSE);
  3          DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP(GRANTEE_NAME => 'SOE2', CONSUMER_GROUP => 'S2_GROUP', GRANT_OPTION => FALSE);
  4  END;
  5  /
PL/SQL PROCEDURE successfully completed.
SQL> BEGIN
  2          DBMS_RESOURCE_MANAGER.CLEAR_PENDING_AREA();
  3          DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA();
  4          DBMS_RESOURCE_MANAGER.CREATE_PLAN(PLAN => 'SWINGBENCH_TEST',COMMENT => 'soe plan');
  5          DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(PLAN => 'SWINGBENCH_TEST', GROUP_OR_SUBPLAN => 'SOE_GROUP',COMMENT => 'soe', MGMT_P1 => 75);
  6          DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(PLAN => 'SWINGBENCH_TEST', GROUP_OR_SUBPLAN => 'S2_GROUP',COMMENT => 'soe2', MGMT_P1 => 25);
  7          DBMS_RESOURCE_MANAGER.CREATE_PLAN_DIRECTIVE(PLAN => 'SWINGBENCH_TEST', GROUP_OR_SUBPLAN => 'OTHER_GROUPS',COMMENT => 'soe3', MGMT_P2 => 100);
  8          DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA();
  9          DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
 10  END;
 11  /
PL/SQL PROCEDURE successfully completed.
SQL> SHOW parameter resource_manager_plan
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_manager_plan                string      DEFAULT_PLAN
SQL> ALTER system SET resource_manager_plan=SWINGBENCH_TEST;
System altered.
SQL>  SHOW parameter resource_manager_plan
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_manager_plan                string      SWINGBENCH_TEST

关于资源管理器这里就不多介绍了,简单描述一下上面的设置。首先创建两个消费组,将SOE用户映射到SOE_GROUP,将SOE2映射到S2_GROUP。对SOE和SOE2用户授权,使其拥有切换到对应消费组的权限。最后进行CPU时间片的分配,75%的资源分配给SOE_GROUP,25%的资源分配给S2_GROUP。
这时再次SWINGBENCH进行压力测试,分别使用SOE和SOE2执行相同的压力测试,并发连接3000。对于连接SOE用户的测试程序,3000的并发并未造成系统的超时。但是SOE2用户的连接由于配置的CPU时间片资源只有系统的1/4,因此在3000连接的时候出现了大量的连接超时会话,压力测试程序已经基本上没有响应了。
使用资源管理器和INSTANCE STAGE并不只是一个数据库和多个数据库的区别,事实上二者的还有一个主要的区别就是CPU使用的划分上。对于INSTANCE STAGE而言,分配了多少CPU_COUNT,那么这个实例就只能使用这么多CPU资源,即使整个服务器上只有当前一个数据库在运行,即使系统的IDLE再高,这个实例所使用的CPU也不会超过CPU_COUNT的限制。而资源管理器则完全不同,事实上即使SOE2用户配置了25%的CPU时间片,如果数据库中只有这个用户的会话,那么这个用户可以使用100%的CPU资源。事实上资源管理器的配置效果一般在主机CPU达到100%的时候才能明显的体现出来。
两种资源的划分方法很难说哪种更优一些,如果根据资源如何划分来考虑多个数据库还是多个SCHEMA的话,那么多个数据库设置CPU_COUNT更适合服务器上还存在其他应用的情况,而使用资源管理器更有利于最大程度上来使用CPU的资源。

Posted in ORACLE | Tagged , , , , , | Leave a comment

ODA环境同一服务器中资源划分(一)

简单描述如何实现在同一台服务器上不同的应用之间进行资源划分。
这里介绍INSTANCE STAGE的方式。
无论是Exadata还是ODA,服务器的配置都越来越强大。因此都存在着把多个应用集中到一起的需求。
对于Exadata而言,一般来说部署的应用数据量大,并发应用高,很少会有多个应用同时部署在一个数据库服务器上的需求,反而经常是需要RAC中的多个节点同时支持某个应用,因此对于Exadata来说,应用资源划分的解决方案是SERVER POOL。
而ODA则和Exadata不同,由于ODA受扩展性,磁盘容量以及配置的限制,因此把多个应用集成到ODA上,那么这些应用多半都是小应用,考虑到ODA只有两个节点组成的RAC,因此对于ODA来说,如何在同一个服务器上给各个应用划分资源,而尽量减少应用之间的相互干扰就是十分有意义的事情了。
除了利用操作系统上的解决方案外,Oracle提供了两种方式的解决方案。一个是通过把多个应用分布到多个数据库中,通过限制每个数据库可以使用的CPU数量实现,即INSTANCE STAGE;另一个是把所有的应用集中到一个数据库,通过数据库的资源管理器实现资源的划分。
对于INSTANCE STAGE其实很简单,就是通过设置初始化参数CPU_COUNT来限制每个数据库可以使用的CPU数量。当然并不是只要设置了CPU_COUNT就可以生效,这个参数生效的一个前提似乎启用了资源管理器。
虽然INSTANCE STAGE也要用资源管理器,但是资源如何划分并不是通过资源管理器中的设置实现的,使用资源管理区是需要Oracle启用资源划分的功能,从而使得CPU_COUNT参数发挥作用。无论是修改CPU_COUNT初始化参数还是开启资源管理区,都是可以动态生效的。
在ODA上使用SWINGBENCH进行压力测试,选择100G的订单环境进行测试,当并发达到6000左右时,ODA两个服务器的CPU基本跑满,前端SWINGBENCH开始出现连接超时的情况,说明当前这种压力已经是服务器所能支持的最大值了。
此时,如果服务器上存在另一数据库,那么连接这个数据库的应用势必会受到压力测试数据库和应用的影响,应用访问的效率必然严重下降。
而如果部署了INSTANCE STAGE,则可以最大程度上避免这个问题。比如在进行压力测试的数据库上设置:

SQL> SHOW parameter cpu_count
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cpu_count                            INTEGER     24
SQL> ALTER system SET cpu_count=8 scope=BOTH;
System altered.
SQL> SHOW parameter cpu_count
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cpu_count                            INTEGER     8
SQL> SHOW parameter resource_manager_plan
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_manager_plan                string
SQL> ALTER system SET resource_manager_plan=DEFAULT_PLAN;
System altered.
SQL> SHOW parameter plan
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_manager_plan                string      DEFAULT_PLAN

这时再次使用SWINGBENCH进行压力测试,发现当并发达到2000后,就可以逐渐出现连接超时的情况,即使把并发增加到6000,压力测试端出现大量的超时的情况下,数据库上CPU的利用率也一直维持在30%左右,还有将近70%的IDLE。
显然这时其他的数据库在进行操作时不会受到压力测试数据库的影响。对于多个服务器上存在多个数据库的情况,可以根据应用的不同,把服务器的CPU划分给各个数据库实例,从而避免这些数据库之间的相互影响。

Posted in ORACLE | Tagged , , , | Leave a comment

HPUX上出现ORA-27300、ORA-27301、ORA-27302的STATUS 11错误

数据库出现ORA-27300、ORA-27301和ORA-27302错误并最终出现ORA-29702错误,导致数据库实例的崩溃。
数据库版本为10.2.0.4 RAC for HP-UX,详细错误信息为:

Wed Jun 27 04:31:07 2012
Process startup failed, error stack:
Wed Jun 27 04:31:07 2012
Errors IN file /u01/app/oracle/admin/orcl/bdump/orcl2_psp0_1943.trc:
ORA-27300: OS system dependent operation:fork failed WITH STATUS: 11
ORA-27301: OS failure message: Resource temporarily unavailable
ORA-27302: failure occurred at: skgpspawn3
Wed Jun 27 04:31:08 2012
Process J001 died, see its trace file
Wed Jun 27 04:31:08 2012
kkjcre1p: unable TO spawn jobq slave process 
Wed Jun 27 04:31:08 2012
Errors IN file /u01/app/oracle/admin/orcl/bdump/orcl2_cjq0_1965.trc:
Wed Jun 27 04:41:55 2012
Process startup failed, error stack:
Wed Jun 27 04:41:55 2012
Errors IN file /u01/app/oracle/admin/orcl/bdump/orcl2_psp0_1943.trc:
ORA-27300: OS system dependent operation:fork failed WITH STATUS: 11
ORA-27301: OS failure message: Resource temporarily unavailable
ORA-27302: failure occurred at: skgpspawn3
Wed Jun 27 04:41:56 2012
Process q001 died, see its trace file
Wed Jun 27 04:41:56 2012
ksvcreate: Process(q001) creation failed
Wed Jun 27 04:53:16 2012
Process startup failed, error stack:
.
.
.
Errors IN file /u01/app/oracle/admin/orcl/bdump/orcl2_psp0_1943.trc:
ORA-27300: OS system dependent operation:fork failed WITH STATUS: 11
ORA-27301: OS failure message: Resource temporarily unavailable
ORA-27302: failure occurred at: skgpspawn3
Wed Jun 27 05:05:06 2012
Process q001 died, see its trace file
Wed Jun 27 05:05:06 2012
ksvcreate: Process(q001) creation failed
Wed Jun 27 05:13:04 2012
Error: KGXGN aborts the instance (6)
Wed Jun 27 05:13:04 2012
Errors IN file /u01/app/oracle/admin/orcl/bdump/orcl2_lmon_1945.trc:
ORA-29702: error occurred IN Cluster GROUP Service operation
LMON: terminating instance due TO error 29702

从status为11以及fork进程报错判断,导致问题的原因是操作系统无法分配进程。
系统dmesg日志出现大量信息:

proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL
proc: TABLE IS FULL

这也证明了导致问题的原因是当前进程数超过了内核参数的设置。
重新设置操作系统上的nproc和maxuprc的值,根据Oracle的安装文档nproc的值至少为4096,而maxuprc的值为nproc*9/10,如果当前进程数量超过设置的值,则根据实际需求重新调整两个值。

Posted in BUG | Tagged , , , , , , , , , , | Leave a comment